OAuth2 Authentication with Google Cloud Run

Stephen Darling
3 min readApr 15, 2019

--

If you’re a serverless lover like me, chances are you’ve heard of the new Cloud Run GCP service announced at Google Next ’19 last week.

My de-facto serverless choice on GCP has been Cloud Functions for a while now, but without recapping all the new capabilities of Cloud Run, I will come outright and say I was most excited to hear about IAM-managed authentication in Cloud Run. One of the major hurdles I’ve had to overcome with Cloud Functions is that http-triggered functions are 100% invokable by anyone. This may (and most likely will) change in the future, but the proposition to host a REST API service, from a Docker container, with Google-managed authentication got me VERY, VERY excited.

Unfortunately, as excited as I was with this new offering, I was equally as frustrated with the indirect, obscure direction on how to properly authenticate to Cloud Run from Google’s official documentation. At one point I thought I needed to create a new OAuth2 resource in the IAP (Identity-Aware Proxy) service, and then got frustrated when my new Cloud Run service didn’t appear in the “Resources” list. I proceeded to circle various Google docs (more times than I care to admit) before piecing this together and hopefully this will help un-muddy the waters and save you a few hours and headaches.

If you’d prefer to jump to the final solution check out the repo here.

Create a service with unauthenticated access disabled

This is pretty straightforward from the quickstart docs. The only change to this tutorial is, instead of pressing “Y” to allow unauthenticated access click “N” or no. We don’t want this service to be “invoke-able” from unauthenticated people/resource.

Create a service account and grant it the Cloud Run/Invoker role

Again, I won’t walk through the steps to create a service account, but you should be able to follow along here. The important part when creating the account is to make sure you download the .json version of the service account credentials and keep them local to this project.

Once you’ve created the service account, login to the GCP console and do the following:

  • Navigate to the Cloud Run landing page
  • Select your service and click on the bar (NOT the link to the service)
  • In the new permissions pane on the right, click “ADD MEMBER”
  • Enter your service account email address and grant it the “Cloud Run/Invoker” role

Get an access token

This was the hardest part for me (personally) to wrap my head around. The gist of this flow is as follows:

  • Locally create a self-signed JWT targeted to your new Cloud Run Service
  • Send a POST request to google’s OAuth2 token endpoint to retrieve an access token

Self-signed JWT

This will pull the private_key and private_key_id from the service account .json file you downloaded earlier and then encode them with RSA-standard encryption. Also importantly, it will point the aud (read audience) to Google’s OAuth2 token endpoint and the target_audience to the new Cloud Run service URL:

The important thing to take note of (above) is that we’re authenticating against Google’s generic OAuth2 token endpoint and NOT an IAP OAuth2 resource. This was something not made explicitly clear in the docs that I want to reiterate here. The target_audience claim in this step specifies the Cloud Run resource, NOT a client_id/secret from a separate IAP endpoint.

Retrieve an access token from Google

Once we have the locally-signed JWT, we need to send it to Google to provide us with an access token we can use as a Bearer token in future REST requests:

Include this access token in any subsequent REST calls to your Cloud Run endpoint

Now that we have an access token we can send this with our authorization header to subsequent REST calls to access this authenticated endpoint:

Done!

Hopefully this helps you on your next/first Cloud Run deployment. Please feel free to leave any comments/questions about what you’ve read here or related.

I’ve created a sample repo on GitHub that takes this tutorial from start-to-finish. Please feel free to fork this and check back as GCP evolves this service.

--

--