Skip to content

Latest commit

 

History

History
146 lines (102 loc) · 7.24 KB

README.md

File metadata and controls

146 lines (102 loc) · 7.24 KB

License Active Maven Central javadoc codecov

simplegoogleidtoken

simplegoogleidtoken is a lightweight Java library for effortlessly exchanging Google Cloud Service Account credentials for Google ID tokens

Purpose

This library is intended to simplify the process of exchanging Google Cloud Service Account credentials for Google ID tokens. It is configurable so when used in GCP the service account assigned to the infrastructure can be used to generate the Google ID token. When used in other envirioment the service account credentials JSON file can be provided and used to request the Google ID token.

The tokens are generated by calling the Google https://oauth2.googleapis.com/token endpoint with the urn:ietf:params:oauth:grant-type:jwt-bearer grant type specifying a target audience that is included in the ID token.

The issuer of these tokens will be https://accounts.google.com which has a JWKS endpoint available at https://www.googleapis.com/oauth2/v3/certs.

The reasoning behind this library is not for calling Google APIs but for calling other APIs that utilize Google ID tokens for authentication. By targeting a light weight implementation for use cases outside of GCP the library is able to provide a simple and easy to obtain Google ID tokens.

Getting Started

This library requires Java 17 and is available in the Maven Central Repository:

<dependency>
    <groupId>com.unitvectory</groupId>
    <artifactId>simplegoogleidtoken</artifactId>
    <version>0.0.3</version>
</dependency>

When utilizing this library and running on GCP the google-auth-library-oauth2-http library is required. This library is available on Maven Central and must be included in addition to simplegoogleidtoken. This optional dependency is not needed if the service account credentials JSON file is provided directly. This is intentional to reduce the number of required dependencies which is limited to only GSON as the mandatory dependency.

<dependency>
    <groupId>com.google.auth</groupId>
    <artifactId>google-auth-library-oauth2-http</artifactId>
    <version>1.23.0</version>
</dependency>

Usage

This library provides SimpleGoogleIdToken which uses SimpleRequest to specify the target audience and SimpleResponse to return the ID token. In the case of an error the SimpleSignException or SimpleExchangeException` will be throw.

When running on GCP this library can utilize the metadata service to obtain the ID tokens without the need to have the service account credentials JSON file. The default behavior for SimpleGoogleIdToken is to use the metadata service to obtain the ID token using the ServiceAccountDefaultGoogleCredentialsConfig configuration object which does not need to explicitly be provided.

package example;

import com.unitvectory.simplegoogleidtoken.SimpleGoogleIdToken;
import com.unitvectory.simplegoogleidtoken.SimpleRequest;

public class GCPExample {

    public String getIdToken() {

        String audience = "https://example.com";

        SimpleGoogleIdToken simpleGoogleIdToken = SimpleGoogleIdToken.builder().build();

        String idToken = simpleGoogleIdToken
                .getIdToken(SimpleRequest.builder().withTargetAudience(audience).build()).getIdToken();

        return idToken;
    }
}

When running outside of GCP the service account credentials JSON file can be provided to the library. The ServiceAccountFileConfig configuration object can be used to provide the path to the service account credentials JSON file. Alternatively ServiceAccountJsonConfig can be used to provide the service account credentials JSON as a string directly.

package example;

import com.unitvectory.simplegoogleidtoken.ServiceAccountFileConfig;
import com.unitvectory.simplegoogleidtoken.SimpleGoogleIdToken;
import com.unitvectory.simplegoogleidtoken.SimpleRequest;

public class LocalExample {

    public String getIdToken(String serviceAccountKeyFilePath) {

        String audience = "https://example.com";

        SimpleGoogleIdToken simpleGoogleIdToken = SimpleGoogleIdToken.builder().withServiceAccountConfig(
                ServiceAccountFileConfig.builder().withFilePath(serviceAccountKeyFilePath).build()).build();

        String idToken = simpleGoogleIdToken
                .getIdToken(SimpleRequest.builder().withTargetAudience(audience).build()).getIdToken();

        return idToken;
    }
}

Under the Covers

How does GCP's API work for Identity tokens? This is accomplished through Google's OAuth endpoint. The following is a brief overview of how this token exchange occurs which is also a description of what this library implements, this isn't particurally complicated.

The POST payload here is a application/x-www-form-urlencoded payload with a grant type of urn:ietf:params:oauth:grant-type:jwt-bearer with the assertion parameter including the JWT from the service account.

POST https://oauth2.googleapis.com/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=TOKENHERE

The assertion is a JWT with the following format...

The header Google expects for this are:

{
  "alg": "HS256",
  "typ": "JWT"
}

The payload is as follows with the key input being target_audience as this will be the audience of the generated token.

{
    "iss": "example-service-account@example.iam.gserviceaccount.com",
    "sub": "example-service-account@example.iam.gserviceaccount.com",
    "aud": "https://oauth2.googleapis.com/token",
    "iat": 1723155553,
    "exp": 1723159153,
    "target_audience": "https://targetaudience.example.com"
}

In the case that a JSON file from a GCP service account is being used, that JSON file looks like the following. The two key attributes here are client_email which is used in bothe the iss and sub of the JWT that is being sigened and the private_key that is being used for the signing.

{
  "type": "service_account",
  "project_id": "example",
  "private_key_id": "00000000000000000000000000000000000000000",
  "private_key": "-----BEGIN PRIVATE KEY-----\nPRIVATEKEYGOESHERE\n-----END PRIVATE KEY-----\n",
  "client_email": "example-service-account@example.iam.gserviceaccount.com",
  "client_id": "0000000000000000000000",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/example-service-account%40example.iam.gserviceaccount.com",
  "universe_domain": "googleapis.com"
}