Using OAuth 2.0 to authenticate server Applications against Google Services
I was recently asked to provide instructions for authenticating a C# server Application against a Google Cloud Service without using Google or 3rd party SDKs. To easily repeat the steps, I decided to implement them in PowerShell using only .NET classes. This also allows to simply port it to e.g. C#.
The steps for using OAuth 2.0 with Google APIs are well documented. It also mentions a list of available client libraries for many popular programming languages. I strongly suggest using these libraries as they are well maintained and implementing security related code can often lead to severe security issues if not done right. OAuth 2.0 is based on JSON Web Token (JWT) which is an open standard (RFC 7519). Therefore an alternative to the Google SDKs are JWT libraries which are available for all kinds of programming languages.
To understand how requesting OAuth 2.0 tokens works it may be useful to carry out the steps manually. A good generic introduction to JWT is provided by jwt.io. They also offer a nice JWT Debugger which can help figuring out problems in the process.
The JWT flow consists of creating a JWT, signing the JWT, forming the access token request, and handling the token response. The access token can then be used to authenticate against a Google API.
The most difficult step is signing of the JWT which requires a secret or private key. For Google Cloud Services, the private key of a service account is required.
A service account can be created in the Google Cloud Shell with
gcloud iam service-accounts create $ServiceAccountName
Grant a role to the service account to access required services. To execute queries in BigQuery the role
roles/bigquery.jobUser is sufficient and can be set in the Google Cloud Shell with
gcloud projects add-iam-policy-binding $GOOGLE_CLOUD_PROJECT --member="serviceAccount:$ServiceAccountName@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com" --role="roles/bigquery.jobUser"
The service account key can be a Google managed key or a user provided key. The Google managed key can be used for signing a maximum of two weeks and need to be rotated regularly. A user managed key needs to be created externally and can be used for a longer duration with larger implications if the key gets into the wrong hands unnoticed.
A self signed certificate with an expiration in 2 years can be generated in the Google Cloud Shell using
openssl req -x509 -nodes -newkey rsa:2048 -days 730 -keyout private_key.pem -out public_key.pem -subj “/CN=unused”
Store the private key file (in this case private_key.pem) in a secure location! Whoever has access to the key can use Cloud resources as permitted via the role of the service account!
The public key needs to be added to the service account keys to be able to authenticate with the private key. The public key can be added in the Google Cloud Shell using
gcloud iam service-accounts keys upload public_key.pem — iam-account=$ServiceAccountName@$GOOGLE_CLOUD_PROJECT.iam.gserviceaccount.com
After a service account and service account key have been created it is possible to request OAuth 2.0 tokens.
As .NET does not support PEM certificates, you need to convert public_key.pem and private_key.pem to a PKCS12 file using openssl. I suggest to use “notasecret” as password to match the password of Google managed service account P12 files.
Create pkcs12 file with openssl in the Google Cloud Shell using
openssl pkcs12 -in public_key.pem -inkey private_key.pem -export -out certificate.p12
The following steps show the JWT authentication and an example query on a public BigQuery dataset (which is free of charge). A detailed explanation of the steps can be found in the Google IAM documentation Using OAuth 2.0 for Server to Server Applications. Open the steps in Cloud shell, adapt the configuration variables and run it in PowerShell which can be started with
The flow diagram shown is taken from the Google Developer documentation and are released under Creative Commons Attribution 4.0 License.