or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

adc.mdcrypto.mdexternal-identity.mdindex.mdoauth2.mdservice-accounts.mdtoken-management.md
tile.json

token-management.mddocs/

Token Management

Utilities for token refresh, validation, credential management, downscoped tokens, and service account impersonation.

Capabilities

User Refresh Client

Client for refreshing user credentials using refresh tokens.

/**
 * Client for refreshing user OAuth2 credentials
 */
class UserRefreshClient extends AuthClient {
  constructor(options?: UserRefreshClientOptions);
  
  /** Refresh access token using refresh token */
  refreshAccessToken(): Promise<RefreshAccessTokenResponse>;
  
  /** Get access token, refreshing if necessary */
  getAccessToken(): Promise<{ token?: string | null; res?: GaxiosResponse }>;
  
  /** Get request headers */
  getRequestHeaders(): Promise<{ [key: string]: string }>;
  
  /** Create scoped version of client */
  createScoped(scopes: string | string[]): UserRefreshClient;
}

interface UserRefreshClientOptions {
  /** Client ID */
  clientId?: string;
  /** Client secret */
  clientSecret?: string;
  /** Refresh token */
  refreshToken?: string;
  /** OAuth2 scopes */
  scopes?: string | string[];
  /** Eager refresh threshold in milliseconds */
  eagerRefreshThresholdMillis?: number;
  /** Force refresh on failure */
  forceRefreshOnFailure?: boolean;
}

interface RefreshAccessTokenResponse {
  /** New credentials */
  credentials: Credentials;
  /** HTTP response */
  res: GaxiosResponse | null;
}

Usage Examples:

import { UserRefreshClient } from "google-auth-library";

// Create refresh client
const refreshClient = new UserRefreshClient({
  clientId: 'client-id.googleusercontent.com',
  clientSecret: 'client-secret',
  refreshToken: 'refresh-token-from-oauth-flow'
});

// Refresh and get new access token
const { credentials } = await refreshClient.refreshAccessToken();
console.log('New access token:', credentials.access_token);

// Make authenticated request
const response = await refreshClient.request({
  url: 'https://www.googleapis.com/oauth2/v1/userinfo'
});

Impersonated Client

Service account impersonation for accessing resources with different permissions.

/**
 * Service account impersonation client
 * Allows one service account to impersonate another
 */
class Impersonated extends AuthClient {
  constructor(options: ImpersonatedOptions);
  
  /** Get access token by impersonating service account */
  getAccessToken(): Promise<{ token?: string | null; res?: GaxiosResponse }>;
  
  /** Get request headers */
  getRequestHeaders(): Promise<{ [key: string]: string }>;
  
  /** Sign blob using impersonated service account */
  sign(blobToSign: string): Promise<string>;
  
  /** Get service account email */
  getCredentials(): Promise<{ client_email: string }>;
}

interface ImpersonatedOptions {
  /** Source credentials for impersonation */
  sourceClient: AuthClient;
  /** Service account email to impersonate */
  targetPrincipal: string;
  /** Delegates for impersonation chain */
  delegates?: string[];
  /** Target scopes */
  targetScopes: string[];
  /** Token lifetime in seconds (max 3600) */
  lifetime?: number | string;
  /** Quota project ID */
  quotaProjectId?: string;
}

Usage Examples:

import { GoogleAuth, Impersonated } from "google-auth-library";

// Create source client (your credentials)
const auth = new GoogleAuth();
const sourceClient = await auth.getClient();

// Create impersonated client
const impersonatedClient = new Impersonated({
  sourceClient: sourceClient,
  targetPrincipal: 'target-service-account@project.iam.gserviceaccount.com',
  targetScopes: ['https://www.googleapis.com/auth/cloud-platform'],
  lifetime: 3600 // 1 hour
});

// Get access token for impersonated service account
const { token } = await impersonatedClient.getAccessToken();

// Use impersonated client for requests
const response = await impersonatedClient.request({
  url: 'https://storage.googleapis.com/storage/v1/b',
  params: { project: 'target-project' }
});

Downscoped Client

Client with downscoped access to resources using Credential Access Boundaries.

/**
 * Downscoped client with restricted access to resources
 * Uses Credential Access Boundaries to limit token scope
 */
class DownscopedClient extends AuthClient {
  constructor(options: DownscopedClientOptions);
  
  /** Get downscoped access token */
  getAccessToken(): Promise<{ token?: string | null; res?: GaxiosResponse }>;
  
  /** Get request headers */
  getRequestHeaders(): Promise<{ [key: string]: string }>;
}

interface DownscopedClientOptions {
  /** Source credentials for downscoping */
  sourceClient: AuthClient;
  /** Credential access boundary rules */
  credentialAccessBoundary: CredentialAccessBoundary;
  /** Quota project ID */
  quotaProjectId?: string;
}

interface CredentialAccessBoundary {
  /** Access boundary rules */
  accessBoundaryRules: AccessBoundaryRule[];
}

interface AccessBoundaryRule {
  /** Available resource (e.g., Cloud Storage bucket) */
  availableResource: string;
  /** Available permissions */
  availablePermissions: string[];
  /** Availability condition (CEL expression) */
  availabilityCondition?: AvailabilityCondition;
}

interface AvailabilityCondition {
  /** CEL expression for condition */
  expression: string;
  /** Condition title */
  title?: string;
  /** Condition description */
  description?: string;
}

Usage Examples:

import { GoogleAuth, DownscopedClient } from "google-auth-library";

// Create source client
const auth = new GoogleAuth();
const sourceClient = await auth.getClient();

// Define access boundary - restrict to specific bucket and objects
const credentialAccessBoundary = {
  accessBoundaryRules: [
    {
      availableResource: '//storage.googleapis.com/projects/_/buckets/my-bucket',
      availablePermissions: [
        'inRole:roles/storage.objectViewer',
        'inRole:roles/storage.objectCreator'
      ],
      availabilityCondition: {
        expression: 'request.time < timestamp("2024-01-01T00:00:00Z")'
      }
    }
  ]
};

// Create downscoped client
const downscopedClient = new DownscopedClient({
  sourceClient: sourceClient,
  credentialAccessBoundary: credentialAccessBoundary
});

// Get downscoped token (limited to specified resources)
const { token } = await downscopedClient.getAccessToken();

// Use downscoped client - only has access to my-bucket
const response = await downscopedClient.request({
  url: 'https://storage.googleapis.com/storage/v1/b/my-bucket/o'
});

ID Token Client

Client for ID token operations and verification.

/**
 * ID token client for OpenID Connect operations
 */
class IdTokenClient extends AuthClient {
  constructor(options: IdTokenClientOptions);
  
  /** Get ID token for target audience */
  getIdToken(targetAudience: string): Promise<string>;
  
  /** Get request headers with ID token */
  getRequestHeaders(): Promise<{ [key: string]: string }>;
}

interface IdTokenClientOptions {
  /** Target audience for ID token */
  targetAudience: string;
  /** ID token provider */
  idTokenProvider: IdTokenProvider;
}

interface IdTokenProvider {
  /** Fetch ID token for audience */
  fetchIdToken(audience: string): Promise<string>;
}

IAM Auth

Utility for IAM-related authentication operations.

/**
 * IAM authentication utility
 */
class IAMAuth extends AuthClient {
  constructor(options?: { [key: string]: any });
  
  /** Get request metadata for IAM operations */
  getRequestMetadata(url?: string): Promise<RequestMetadata>;
}

interface RequestMetadata {
  [key: string]: string | string[];
}

Pass Through Client

Pass-through authentication client for testing and development.

/**
 * Pass-through client that doesn't perform authentication
 * Useful for anonymous access, local emulators, and testing environments
 */
class PassThroughClient extends AuthClient {
  constructor();
  
  /** Get access token (returns empty object) */
  getAccessToken(): Promise<GetAccessTokenResponse>;
  
  /** Get request headers (returns empty Headers object) */
  getRequestHeaders(): Promise<Headers>;
  
  /** Make request without authentication headers */
  request<T>(opts: GaxiosOptions): Promise<GaxiosResponse<T>>;
}

Usage Examples:

import { PassThroughClient } from "google-auth-library";

// Create pass-through client for testing
const passthroughClient = new PassThroughClient();

// Make unauthenticated request (useful for local emulators)
const response = await passthroughClient.request({
  url: 'http://localhost:8080/api/data',
  method: 'GET'
});

// Use with Google Cloud emulators
const emulatorResponse = await passthroughClient.request({
  url: 'http://localhost:8080/storage/v1/b/test-bucket/o',
  method: 'GET'
});

ID Token Client

Client for ID token operations and verification for OpenID Connect workflows.

/**
 * ID token client for OpenID Connect operations
 * Retrieves ID tokens from metadata servers or other providers
 */
class IdTokenClient extends OAuth2Client {
  constructor(options: IdTokenOptions);
  
  /** Get request metadata with ID token */
  getRequestMetadata(): Promise<RequestMetadataResponse>;
}

interface IdTokenOptions extends OAuth2ClientOptions {
  /** The client to make the request to fetch an ID token */
  idTokenProvider: IdTokenProvider;
  /** The audience to use when requesting an ID token */
  targetAudience: string;
}

interface IdTokenProvider {
  /** Fetch ID token for target audience */
  fetchIdToken(targetAudience: string): Promise<string>;
}

interface RequestMetadataResponse {
  headers?: Headers;
}

Usage Examples:

import { IdTokenClient } from "google-auth-library";

// Custom ID token provider
const idTokenProvider = {
  fetchIdToken: async (audience: string) => {
    // Implement custom logic to fetch ID token
    // e.g., from metadata server, external service, etc.
    return await fetchFromCustomSource(audience);
  }
};

// Create ID token client
const idTokenClient = new IdTokenClient({
  targetAudience: 'https://my-service.example.com',
  idTokenProvider: idTokenProvider
});

// Get authenticated request metadata
const metadata = await idTokenClient.getRequestMetadata();

// Use headers in requests
const response = await fetch('https://my-service.example.com/api', {
  headers: metadata.headers
});

Credential Types

interface Credentials {
  /** OAuth2 access token */
  access_token?: string | null;
  /** OAuth2 refresh token */
  refresh_token?: string | null;
  /** Token scope */
  scope?: string;
  /** Token type (usually 'Bearer') */
  token_type?: string;
  /** OpenID Connect ID token */
  id_token?: string | null;
  /** Token expiry timestamp (milliseconds) */
  expiry_date?: number | null;
}

interface RefreshOptions {
  /** Eager refresh threshold in milliseconds */
  eagerRefreshThresholdMillis?: number;
  /** Force refresh on failure */
  forceRefreshOnFailure?: boolean;
}

Token Validation

/**
 * Validate token expiry and refresh if needed
 */
function isTokenExpiring(credentials: Credentials, eagerRefreshThresholdMillis?: number): boolean;

/**
 * Check if credentials need refresh
 */
function shouldRefreshToken(credentials: Credentials): boolean;

Error Handling

Common token management errors:

  • Token expired: Access token has expired and needs refresh
  • Invalid refresh token: Refresh token is invalid or revoked
  • Impersonation failed: Insufficient permissions for service account impersonation
  • Downscoping failed: Invalid access boundary rules
try {
  const { credentials } = await refreshClient.refreshAccessToken();
} catch (error) {
  if (error.response?.data?.error === 'invalid_grant') {
    console.error('Refresh token is invalid or expired');
    // Re-authenticate user
  } else if (error.response?.status === 403) {
    console.error('Insufficient permissions for token refresh');
  }
}

try {
  const impersonatedClient = new Impersonated(options);
  const { token } = await impersonatedClient.getAccessToken();
} catch (error) {
  if (error.message.includes('Permission denied')) {
    console.error('Source account cannot impersonate target service account');
    console.error('Grant "Service Account Token Creator" role to source account');
  }
}