Google APIs Authentication Client Library for Node.js providing OAuth2, JWT, and Application Default Credentials
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Utilities for token refresh, validation, credential management, downscoped tokens, and service account impersonation.
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'
});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' }
});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'
});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>;
}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 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'
});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
});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;
}/**
* Validate token expiry and refresh if needed
*/
function isTokenExpiring(credentials: Credentials, eagerRefreshThresholdMillis?: number): boolean;
/**
* Check if credentials need refresh
*/
function shouldRefreshToken(credentials: Credentials): boolean;Common token management errors:
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');
}
}