AIP-4111

Self-signed JWT

Self-signed JWT (JSON Web Token) for Google APIs was introduced in 2014 to provide a more efficient auth stack for Cloud APIs being accessed via service accounts by bypassing the intermediate step of exchanging client assertions for OAuth tokens. A self-signed JWT is a spec-conforming JWT that is locally signed by the service account private key. Since many Cloud APIs accept self-signed JWT in place of traditional access tokens, it is now considered a standard authentication method.

Note: Because this AIP describes guidance and requirements in a language-neutral way, it uses generic terminology which may be imprecise or inappropriate in certain languages or environments.

Guidance

This section describes the general guidance of supporting self-signed JWT as a means of authentication.

Application Default Credentials

Supporting self-signed JWT is considered a part of application default credentials. To understand the overall flow, please read AIP-4110.

Scope vs. Audience

In the past, the self-signed JWT was only applicable with audience. Recently, the usage of the "scope" claim in self-signed JWTs is now allowed in the Google Cloud auth ecosystem, which makes the self-signed JWT usable with both audience and scope. However, caller must not specify scope and audience at the same time to prevent potential conflicts.

Opt-in Strategy

Currently, this scope support for JWT is gated behind a configurable boolean option UseJWTAccessWithScope(the actual naming may vary depending on the programming language), as the feature is not supported for all Cloud API service backends. The default value of this boolean is false, and to use scope with self-signed JWT, caller must specify this option as true. Otherwise the OAuth exchange flow should be used instead when scope is provided. The API clients should try to automatically determine this option with the appropriate value based on the APIs, so this complexity is not exposed to the upper-layer developer.

Default Authentication Method For Service Account Keys

Considering its better efficiency and reliability comparing with OAuth flow (bypassing the exchanging step), ADC should use self-signed JWT as the default authentication flow when service account key is provided as the source credential.

In other words, ADC should choose the OAuth flow over the self-signed JWT flow only if scope is provided and JWT is not enabled via UseJWTAccessWithScope.

Expected Behavior

To support self-signed JWT, the auth libraries must follow the steps below:

1. Load the service account ID JSON file. Please note that the self-signed JWT only supports service account ID credential type.

2. Using any standard JWT library, such as one found at jwt.io, create a JWT with a header and payload like the following examples:

(1) Example of using audience:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "abcdef1234567890"
}
{
  "iss": "123456-compute@developer.gserviceaccount.com",
  "sub": "123456-compute@developer.gserviceaccount.com",
  "aud": "https://pubsub.googleapis.com/",
  "iat": 1511900000,
  "exp": 1511903600
}

(2) Example of using scope:

{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "abcdef1234567890"
}
{
  "iss": "123456-compute@developer.gserviceaccount.com",
  "sub": "123456-compute@developer.gserviceaccount.com",
  "scope": "https://www.googleapis.com/auth/cloud-platform",
  "iat": 1511900000,
  "exp": 1511903600
}
  • For the kid field in the header, specify the service account's private key ID. You can find this value in the private_key_id field of the service account JSON file.

  • For the iss and sub fields, specify the service account's email address. You can find this value in the client_email field of the service account JSON file.

  • For the aud field, specify the audience. The default audience value should be https://[SERVICE]/. (e.g. https://pubsub.googleapis.com/)

  • For the scope field, specify the scope. Please note that aud and scope cannot be specified at the same time.

  • For the iat field, specify the current Unix time, and for the exp field, the value must be exactly 3600 seconds later, when the JWT will expire.

3. Sign the JWT with RSA-256 using the private key found in the service account JSON file.

Changelog

  • 2019-08-13: Add a section for application default credential.
  • 2021-06-02: Update scope support.