GoogleComputeEngine service account authentication

Authenticate app with service account for working with Google services

  • Share

In case you are a .NET developer and you are using Google Cloud platform, eventually your apps or services will have to interact with Google Cloud (GCE) services. Good thing is that complete GCE is exposed through REST API.

Whole authentication is done through OAuth 2.0, but the authentication of website applications and your services which might be running in background on your server is not the same. Better said should not be the same and one of the main reasons is that for service you do not have a real used consent to use the app.

Of course, you can do this by logging in using browser and acquire code and authentication token, but this is not actually the proper way of doing this. For this kind of requirement Google has something called Service Accounts (https://console.cloud.google.com/iam-admin/serviceaccounts/).

Once you create a service account, you will be offered to download P12 or JSON certificate.

In this article I will be showing how to use P12 certificate, so once you create your account you should pick P12 and download it locally to your computer. Take care of this file as you will be using it to authenticate your application to Google regardless of the type of the service from Google you want to use (Analytics, Storage, Stackdriver, bigData...)

Since we got the certificate, we can switch to code. I will use GCE Storage service for this example, but it is applicable to any Google service long as you enable the service API in the API Manager/Dashboard (https://console.cloud.google.com/apis/dashboard)

Before you start you need to add a reference to Google.Cloud.Storage.V1 nuget package in your project. Basically, you only need Google.Apis.Core and Google.Apis nuget, but since this example is showing usage of Google Cloud Storage we are going to reference that once and it will pull the other two basic ones mentioned. Now to stat with the code:

            using (var certificate = new X509Certificate2("<P12 Certificate Path Here>", "notasecret", X509KeyStorageFlags.Exportable))
            {
                var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer("<Service Account name generated in Google Developer Console>")
                {
                    Scopes = new[] {
                        StorageService.Scope.DevstorageReadWrite
                    }
                }.FromCertificate(certificate));

                /* Use Google Service with this authentication*/

            }
    

Regarding the scopes, you can use the enumeration from the nuget, depending which Google service and nuget related to that service or you can use it as a string. List of scopes can be found at https://developers.google.com/identity/protocols/googlescopes. I prefer using enumeration over string, but you can use which ever suits for you better. So code above is equivalent to the following one:

            using (var certificate = new X509Certificate2("<P12 Certificate Path Here>", "notasecret", X509KeyStorageFlags.Exportable))
            {
                var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer("<Service Account name generated in Google Developer Console>")
                {
                    Scopes = new[] {
                        @"https://www.googleapis.com/auth/devstorage.read_write"
                    }
                }.FromCertificate(certificate));

                /* Use Google Service with this authentication*/

            }
    

Now we can start using the service:

            using (var certificate = new X509Certificate2("<P12 Certificate Path Here>", "notasecret", X509KeyStorageFlags.Exportable))
            {
                var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer("<Service Account name generated in Google Developer Console>")
                {
                    Scopes = new[] {
                        StorageService.Scope.DevstorageReadWrite
                    }
                }.FromCertificate(certificate));

                using (var cloudStorageService = new StorageService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "My Application Name",
                }))
                {
                    /* Using the service through the service object instance */
                }
            }
    
Note

For the application name you can use any string. I personally like to use the full class name from where the service is used from (this is usually Windows service class) and I initialize it in the static class constructor so it does not slow down code by executing the reflection:

static String applicatioName = typeof(Program).FullName;
    

Whole sample is wraed in using syntax, so no worries about the resource releasing :)

References

  • Share

Disclaimer

Purpose of the code contained in snippets or available for download in this article is solely for learning and demo purposes. Author will not be held responsible for any failure or damages caused due to any other usage.

Comments for this article

comments powered by Disqus