Skip to main content
Glama
oauth.ts2.95 kB
import * as oidc_client from 'openid-client'; export interface TokenExchangeConfig { authzServerBaseUrl: string; mcpServerClientId: string; mcpServerClientSecret: string; tokenExchangeScope: string[]; backendApiResource?: string; backendApiAudience?: string; } /** * OAuth server configuration cache */ let cachedAuthServerConfig: oidc_client.Configuration | null = null; /** * Gets or creates a cached OpenID Configuration instance */ export async function getOAuthServerConfiguration( config: TokenExchangeConfig ): Promise<oidc_client.Configuration> { if (cachedAuthServerConfig) return cachedAuthServerConfig; try { cachedAuthServerConfig = await oidc_client.discovery( new URL(config.authzServerBaseUrl), config.mcpServerClientId, config.mcpServerClientSecret, undefined, { execute: [oidc_client.allowInsecureRequests] } ); return cachedAuthServerConfig; } catch (err: unknown) { const errorMessage = err instanceof Error ? err.message : String(err); console.error('Failed to initialize OpenID client:', errorMessage); throw new Error('Failed to initialize OAuth client for token exchange'); } } /** * Performs an OAuth 2.0 Token Exchange (RFC 8693) * * @param subjectToken - The access token received from the client or another API * @param config - Token exchange configuration * @returns The new access token to use for calling a downstream API */ export async function performTokenExchange( subjectToken: string, config: TokenExchangeConfig ): Promise<string | null> { try { // Discover the Authorization Server's configuration const authServerConfig = await getOAuthServerConfiguration(config); // Execute the token exchange request const requestParams: Record<string, string> = { subject_token: subjectToken, subject_token_type: 'urn:ietf:params:oauth:token-type:access_token', requested_token_type: 'urn:ietf:params:oauth:token-type:access_token', scope: config.tokenExchangeScope.join(' ') }; if (config.backendApiResource) { requestParams.resource = config.backendApiResource; } if (config.backendApiAudience) { requestParams.audience = config.backendApiAudience; } const response = await oidc_client.genericGrantRequest( authServerConfig, 'urn:ietf:params:oauth:grant-type:token-exchange', requestParams ); // Verify the response contains the expected access token if (!response?.access_token) { console.error('Token exchange succeeded but no access_token was returned:', response); return null; } return response.access_token; } catch (err: unknown) { console.error('Error during token exchange:', err); return null; } } /** * Resets the cached OAuth server configuration (useful for testing) */ export function resetOAuthServerConfigurationCache(): void { cachedAuthServerConfig = null; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/jacopoc/mcp-for-apache-ofbiz'

If you have feedback or need assistance with the MCP directory API, please join our Discord server