Skip to content

Instantly share code, notes, and snippets.

@wvanderdeijl
Last active January 25, 2022 07:59
Show Gist options
  • Save wvanderdeijl/95f511d4f2749b8b6ad38c26f27da251 to your computer and use it in GitHub Desktop.
Save wvanderdeijl/95f511d4f2749b8b6ad38c26f27da251 to your computer and use it in GitHub Desktop.
Auth0 client credentials flow federation to Google Cloud Service Account

Auth0 client credentials flow federation to Google Cloud Service Account

Preparation

Configure OIDC based Workload Identity Federation at Google Cloud (see https://cloud.google.com/iam/docs/configuring-workload-identity-federation). When configuring the identity provider use the following information:

  • Set the issuerURI to https://[TENANT].eu.auth0.com/, so google can retrieve the https://my-tenant.eu.auth0.com/.well-known/openid-configuration configuration file with the public key information
  • Set the attributeCondition to assertion.gty=='client-credentials' && assertion.azp=='[CLIENT-ID]' However, at this stage the auth0 client-id is not yet known, so use a dummy value that we will replace later with the correct client-id
  • Set a single attribute mapping google.subject to assertion.sub so the subject from the auth0 token will be copied to the subject of the (temporary) google credentials. This subject will be [CLIENT-ID]@clients and can be used in Google IAM policies as principal://iam.googleapis.com/projects/[PROJECT]/locations/[LOCATION]/workloadIdentityPools/[POOL]/subject/[CLIENT-ID]@clients

Next, create a service account in Google cloud with the following information:

  • Create the service account
  • Grant roles/iam.serviceAccountTokenCreator on that service account to principal://iam.googleapis.com/projects/[PROJECT]/locations/[LOCATION]/workloadIdentityPools/[POOL]/subject/[CLIENT-ID]@clients This allows a temporary federated credential from auth0 to sign tokens with this service account, effectily impersonating this service account.

In auth0 create an API and set its identifier to the audience that will be required to the google workload identity federation, this is //iam.googleapis.com/projects/[NUMERIC-PROJECT-ID]/locations/global/workloadIdentityPools/[POOL-NAME]/providers/[PROVIDER-NAME]

Next, in auth0 create a "Machine to Machine" application with access to the API you just created in auth0. Note the generated Client ID and Client Secret.

Go back to the Google Cloud workload identity federation provider and change the attributeCondition to reference the correct auth0 client-id.

Getting a Google token with Auth0 client credentials

The first step is to get an access token from auth0 with the client credentials flow:

AUTH0_CLIENT_ID=*********
AUTH0_CLIENT_SECRET=*********
AUTH0_TENANT=*********.eu.auth0.com
AUTH0_AUDIENCE=//iam.googleapis.com/projects/999999999999/locations/global/workloadIdentityPools/MY-POOL/providers/MY-PROVIDER

AUTH0_ACCESS_TOKEN=$(curl --request POST \
  --url "https://$AUTH0_TENANT/oauth/token" \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data grant_type=client_credentials \
  --data client_id=$AUTH0_CLIENT_ID \
  --data client_secret=$AUTH0_CLIENT_SECRET \
  --data audience=$AUTH0_AUDIENCE | jq -r '.access_token')

The next step is to exchange this auth0 access token for a Google STS token:

STS_TOKEN=$(jq -n --arg audience $AUTH0_AUDIENCE --arg subjectToken $AUTH0_ACCESS_TOKEN '{
    audience: $audience,
    grantType: "urn:ietf:params:oauth:grant-type:token-exchange",
    requestedTokenType: "urn:ietf:params:oauth:token-type:access_token",
    scope: "https://www.googleapis.com/auth/cloud-platform",
    subjectTokenType: "urn:ietf:params:oauth:token-type:jwt",
    subjectToken: $subjectToken
}' | curl -X POST https://sts.googleapis.com/v1/token -H 'Content-Type: text/json; charset=utf-8' -d @- | jq -r '.access_token')

You now have a token with temporary credentials. Since we granted roles/iam.serviceAccountTokenCreator on a google service account, you can use these temporary credentials to sign another (custom) JWT with that service account. An example for such a custom token would be to invoke a Google Cloud API Gateway:

AUTH0_SERVICE_ACCOUNT=my-google-service-account@my-project.iam.gserviceaccount.com
TOKEN=$(jq -n --arg time_str "$(date +%s)" --arg iss $AUTH0_SERVICE_ACCOUNT '{
    sub: $iss,
    iss: $iss,
    aud: "http://my-api-gateway.example.com",
    iat: $time_str | tonumber,
    exp: ($time_str | tonumber + 300),
}' | jq '{payload: .|tostring}' | curl -X POST https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/${AUTH0_SERVICE_ACCOUNT}:signJwt \
    -H "Authorization: Bearer $STS_TOKEN" \
    -H 'Content-Type: text/json; charset=utf-8' -d @- | jq -r '.signedJwt')

You can also use these temporary credentials with the google cloud client libraries, the google cloud CLI or your deployment tooling. For more information on using OIDC federation with these libraries and tools see https://cloud.google.com/iam/docs/using-workload-identity-federation#generate-automatic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment