Authenticating using Google OpenID Connect Tokens

salmaan rashid
Jul 19, 2019 · 7 min read

More and more Services that _you_ deploy on Google Cloud can have automatic perimeter authentication enabled by default. What i mean by that is you can now deploy a Cloud Function or Cloud Run instance and automatically enforce IAM policies that allow only certain identities through that you allow. These clients that access your service must present a Google Issued OpenID Connect token.

I often find customers asking how to provide these tokens and so I wrote up this article to help point users on how to acquire and validate ID tokens. The samples provided here are as-is but they do work.

NOTE: Ultimately, a variation of this article will reside on Google Cloud’s documentation. Until that is live, i’ll keep this blog available or later on, redirect to that

Anyway..lets get started:

This section covers authenticating against security perimeters which requires clients present valid OpenID Connect tokens. These security perimeters do not protect Google APIs but your services deployed behind certain Google Cloud Products. For example, if you deploy to Cloud Functions or an application on Cloud Run, you can enable a perimeter such that any client that wants to invoke the function or your application must present an ID token issued by Google.

These tokens are not Oauth2 access_tokens you would use to call a Google Service or API directly such as a Google Compute Engine API or Cloud Storage Bucket but id_tokens that assert identity and are signed by Google.

What is an id_token?

OpenIDConnect (OIDC) tokens are signed JSON Web Tokens JWT used to assert identity and do not necessarily carry any implicit authorization against a resource. These tokens will just declare who the caller is and any service that the token is sent to can verify the token’s integrity by verifying the signature payload provided with the JWT. For more information, see the links in the References section below

If the ID Token is signed and issued by Google, that token can be used as a token against GCP service perimeters because the service can decode the token, verify its signature and finally identify the caller using values within the JWT claim. For example, the JWT header and payload below describes a token that was issued by google ("iss": "https://accounts.google.com"), identifies the caller ("email": "svc_account@.project.gserviceaccount.com"), has not expired (the service will check the exp: field), and finally will verify the JWT is intended for the service or not to "aud": "https://example.com".

{
"alg": "RS256",
"kid": "5d887f26ce32577c4b5a8a1e1a52e19d301f8181",
"typ": "JWT"
}.
{
"aud": "https://example.com",
"azp": "107145139691231222712",
"email": "svc_account@.project.gserviceaccount.com",
"email_verified": true,
"exp": 1556665461,
"iat": 1556661861,
"iss": "https://accounts.google.com",
"sub": "107145139691231222712"
}

Note: the subject (sub) claim in the token above represents the unique internal Google identifier account representing the ID Token.

Whats an Audience?

The aud: field describes the service name this token was created to invoke. If a service receives an id_token, it must verify its integrity (signature), validity (is it expired) and if the aud: field is the predefined name it expects to see. If the names do not match, the service should reject the token as it could be a replay intended for another system.

Both Google Service Accounts and Users can get id_tokens but with an important distinction: User login oauth flows issue id_tokens statically bound to the web or oauth2 client_id the flow as associated with. That is, if a user logs into a web application involving oauth2, the id_token that the provider issues to the browser will have the aud: field bound to the oauth2 client_id.

Service Accounts on the other hand, can participate in a flow where it can receive and id_token from google with an aud: field it specified earlier. These token types issued by Service Accounts are generally the ones discussed in this article.

Sources of Google Issued ID Tokens

There are several ways to get a Google-issued id_token for a Service Account

Service Account JSON certificate

If you have a Google-issued Service account certificate file locally, you can sign the JWT with specific claims and exchange that with google to get a google-issued id_token. While specifying the claims to sign, a predefined claim called target_audience which when set will be used by Google oauth endpoint and reinterpreted as the aud: field in the id_token.

The flow using a json is:

  • 1. Use the service account JSON file to sign a JWT with intended final audience set as target_audience.

Metadata Server

If a metadata server is available while running on Compute Engine, Appengine 2nd Generation, Cloud Functions or even Kubernetes engine, getting an id_token is simple: query the server itself for the token and provide the audience field the token should be for.

For example, the following curl command on any platform with metadata server will return an id_token:

curl -s \ 
-H 'Metadata-Flavor: Google' \ http://metadata/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://example.com`

IAMCredentials generateIdToken()

Google Cloud IAM Credentials API provides a way for one service account to generate short lived tokens on behalf of another. One of the token types it can issue is an id_token via the generateIdToken() endpoint. Making Authorized Requests Once you have an id_token, provide that in the request Authorization header as:

Authorization: Bearer id_token

eg.

curl -v -H "Authorization: Bearer id_token" \
https://some-cloud-run-uc.a.run.app

Services Accepting OIDC tokens for authentication

The following platforms use Google OIDC tokens for access controls. If you deploy an application behind any of of these services, you can optionally enable IAM access controls. What that will do is require any inbound access to a service to provide a valid Google OIDC token.

Furthermore, the token must have its aud: field set to the service name being invoked. For example, to invoke a Cloud Run service, you must setup IAM access for the users (see Managing access via IAM and any ID token provided must have be signed with the aud: field set to the service name itself. If the Cloud Run service is https://svc.-hash-.zone.cloud.run, the audience field must be set to the same

You can also deploy your own service outside of these services and verifying an OpenID Connect token. In this mode, your application that receives an OIDC token will need to manually verify its validity and audience field. You can use application frameworks like to do this like Spring Security, proxies like Envoy or even higher level Services like Istio.

For detailed implementation, see:

Services that include OIDC tokens in webhooks

Other services also support automatically including an OIDC token along with a webhook request

For example, you can configure Cloud Scheduler to emit an OIDC token with a preset audience. When a scheduled tasks fires, an http webhook url will be called and within the header payload, the OIDC token will get transmitted within the Authorization header. The webhook target can be your own application or any of the services listed in the previous section. If your application is running outside of these services listed under Services Accepting OIDC tokens for authentication, you will need to parse and verify the OIDC token.

See:

For detailed implementation, see:

How to get an ID Token

There are several flows to get an ID Token available. The snippets below demonstrate how to

  1. Get an IDToken

Each while using

  • Service Account JSON certificate

Disclaimer: the following snippets potentially use 3rd party libraries and is not supported by Google

Several samples below are just temprorary solutions: google-cloud libraries should eventually support creating and validating ID tokens. The library/language sets where there are pending PRs for this feature is cited below

gcloud

gcloud auth activate-service-account \
--key-file=/path/to/svc_account.json
gcloud auth print-identity-token --audience=https://example.com
  • 7/10/19: gcloud supports only getting an IDToken for Service Account JSON

python

java

go

nodejs

dotnet

How to verify an ID Token?

You can verify OIDC tokens manually if the inbound framework you deployed an application to does automatically perform the validation. In these cases, you the snippets provided above describe how to use google and other libraries to download the public certificates used to sign the JWT

Any validation should not just involve verifying the public certificate and validity but also that the audience claim matches the service being invoked. For more information, see Validating an ID Token. You can find samples here that implement validation.

It is recommend to always verify locally but for debugging, you can use the tokenInfo endpoint or services that decode like jwt.io.

References

Google Cloud - Community

A collection of technical articles published or curated by Google Cloud Developer Advocates. The views expressed are those of the authors and don't necessarily reflect those of Google.

salmaan rashid

Written by

Google Cloud - Community

A collection of technical articles published or curated by Google Cloud Developer Advocates. The views expressed are those of the authors and don't necessarily reflect those of Google.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade