UNPKG

adk-typescript

Version:

TypeScript port of Google's Agent Development Kit (ADK)

325 lines (324 loc) 11.7 kB
"use strict"; /** * Authentication helpers for OpenAPI tools */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.INTERNAL_AUTH_PREFIX = exports.OpenIdConnectWithConfig = exports.OpenIdConnect = exports.OAuth2 = exports.HTTPBearer = exports.HTTPBase = exports.APIKey = exports.APIKeyIn = void 0; exports.tokenToSchemeCredential = tokenToSchemeCredential; exports.serviceAccountDictToSchemeCredential = serviceAccountDictToSchemeCredential; exports.serviceAccountSchemeCredential = serviceAccountSchemeCredential; exports.openidDictToSchemeCredential = openidDictToSchemeCredential; exports.openidUrlToSchemeCredential = openidUrlToSchemeCredential; exports.credentialToParam = credentialToParam; exports.dictToAuthScheme = dictToAuthScheme; const AuthTypes_1 = require("./AuthTypes"); const AuthCredential_1 = require("../../../auth/AuthCredential"); const common_1 = require("../common/common"); const axios_1 = __importDefault(require("axios")); // Types var APIKeyIn; (function (APIKeyIn) { APIKeyIn["header"] = "header"; APIKeyIn["query"] = "query"; APIKeyIn["cookie"] = "cookie"; })(APIKeyIn || (exports.APIKeyIn = APIKeyIn = {})); // Auth scheme classes class APIKey { constructor(config) { this.type_ = config.type_; this.in_ = config.in_; this.name = config.name; } } exports.APIKey = APIKey; class HTTPBase { constructor(config) { this.type_ = config.type_; this.scheme = config.scheme; } } exports.HTTPBase = HTTPBase; class HTTPBearer extends HTTPBase { constructor(config) { super({ type_: config.type_, scheme: config.scheme, }); this.bearerFormat = config.bearerFormat; } } exports.HTTPBearer = HTTPBearer; class OAuth2 { constructor(config) { this.type_ = config.type_; this.flows = config.flows; } } exports.OAuth2 = OAuth2; class OpenIdConnect { constructor(config) { this.type_ = config.type_; this.openIdConnectUrl = config.openIdConnectUrl; } } exports.OpenIdConnect = OpenIdConnect; class OpenIdConnectWithConfig extends OpenIdConnect { constructor(config) { super({ type_: config.type_, openIdConnectUrl: config.openIdConnectUrl, }); this.authorization_endpoint = config.authorization_endpoint; this.token_endpoint = config.token_endpoint; this.scopes = config.scopes; } } exports.OpenIdConnectWithConfig = OpenIdConnectWithConfig; // Prefix for internal auth parameters exports.INTERNAL_AUTH_PREFIX = '__auth_'; /** * Convert a token to a scheme and credential */ function tokenToSchemeCredential(tokenType, location, name, token) { let scheme; let credential = null; if (tokenType.toLowerCase() === 'apikey') { scheme = new APIKey({ type_: AuthTypes_1.AuthSchemeType.apiKey, in_: location, name: name, }); if (token) { credential = { auth_type: AuthCredential_1.AuthCredentialTypes.API_KEY, api_key: token, }; } } else if (tokenType.toLowerCase() === 'oauth2token') { scheme = new HTTPBearer({ type_: AuthTypes_1.AuthSchemeType.http, scheme: 'bearer', bearerFormat: 'JWT', }); if (token) { credential = { auth_type: AuthCredential_1.AuthCredentialTypes.HTTP, http: { scheme: 'bearer', credentials: { token: token } } }; } } return [scheme, credential]; } /** * Convert a service account config dict to a scheme and credential */ function serviceAccountDictToSchemeCredential(config, scopes) { const scheme = new HTTPBearer({ type_: AuthTypes_1.AuthSchemeType.http, scheme: 'bearer', bearerFormat: 'JWT', }); const credential = { auth_type: AuthCredential_1.AuthCredentialTypes.SERVICE_ACCOUNT, service_account: { service_account_credential: { type: config.type, project_id: config.project_id, private_key_id: config.private_key_id, private_key: config.private_key, client_email: config.client_email, client_id: config.client_id, auth_uri: config.auth_uri, token_uri: config.token_uri, auth_provider_x509_cert_url: config.auth_provider_x509_cert_url, client_x509_cert_url: config.client_x509_cert_url, universe_domain: config.universe_domain, }, scopes: scopes, }, }; return [scheme, credential]; } /** * Convert a ServiceAccount to a scheme and credential */ function serviceAccountSchemeCredential(config) { const scheme = new HTTPBearer({ type_: AuthTypes_1.AuthSchemeType.http, scheme: 'bearer', bearerFormat: 'JWT', }); const credential = { auth_type: AuthCredential_1.AuthCredentialTypes.SERVICE_ACCOUNT, service_account: config, }; return [scheme, credential]; } /** * Convert an OpenID Connect config dict to a scheme and credential */ function openidDictToSchemeCredential(configDict, scopes, credentialDict) { // Validate required fields in the OpenID Connect configuration if (!configDict.authorization_endpoint || !configDict.token_endpoint) { throw new Error('Invalid OpenID Connect configuration'); } let clientId; let clientSecret; let redirectUri; // Check if we have google oauth credential format if ('web' in credentialDict) { clientId = credentialDict.web.client_id; clientSecret = credentialDict.web.client_secret; redirectUri = credentialDict.web.redirect_uri; } else { clientId = credentialDict.client_id; clientSecret = credentialDict.client_secret; redirectUri = credentialDict.redirect_uri; } // Validate required fields in the credential dictionary const missingFields = []; if (!clientId) missingFields.push('client_id'); if (!clientSecret) missingFields.push('client_secret'); if (missingFields.length > 0) { throw new Error(`Missing required fields in credential_dict: ${missingFields.join(', ')}`); } const scheme = new OpenIdConnectWithConfig({ type_: AuthTypes_1.AuthSchemeType.openIdConnect, openIdConnectUrl: configDict.openIdConnectUrl || '', authorization_endpoint: configDict.authorization_endpoint, token_endpoint: configDict.token_endpoint, scopes: scopes, }); const credential = { auth_type: AuthCredential_1.AuthCredentialTypes.OPEN_ID_CONNECT, oauth2: { client_id: clientId, client_secret: clientSecret, redirect_uri: redirectUri, }, }; return [scheme, credential]; } /** * Fetch OpenID Connect configuration from a URL and convert to a scheme and credential */ async function openidUrlToSchemeCredential(openidUrl, scopes, credentialDict) { try { const response = await axios_1.default.get(openidUrl, { timeout: 10000 }); const config = response.data; if (!config) { throw new Error('Invalid JSON response'); } // Add openIdConnectUrl to the config config.openIdConnectUrl = openidUrl; return openidDictToSchemeCredential(config, scopes, credentialDict); } catch (error) { if (error instanceof Error && error.message === 'Invalid JSON response') { throw new Error(`Invalid JSON response from OpenID configuration endpoint ${openidUrl}`); } throw new Error(`Failed to fetch OpenID configuration from ${openidUrl}`); } } /** * Convert an auth credential to a parameter and keyword args */ function credentialToParam(authScheme, authCredential) { if (!authCredential) { return [null, null]; } if (authScheme instanceof APIKey) { const paramLocation = authScheme.in_; const paramName = authScheme.name; if (authCredential.auth_type === AuthCredential_1.AuthCredentialTypes.API_KEY && authCredential.api_key) { const param = new common_1.ApiParameter(paramName, paramLocation, {}); const kwargs = { [exports.INTERNAL_AUTH_PREFIX + paramName]: authCredential.api_key }; return [param, kwargs]; } } else if (authScheme instanceof HTTPBearer || authScheme instanceof OAuth2 || authScheme instanceof OpenIdConnect) { // For bearer tokens, always use Authorization header const paramName = 'Authorization'; const paramLocation = 'header'; if (authCredential.auth_type === AuthCredential_1.AuthCredentialTypes.HTTP && authCredential.http?.scheme === 'bearer' && authCredential.http?.credentials?.token) { const param = new common_1.ApiParameter(paramName, paramLocation, {}); const kwargs = { [exports.INTERNAL_AUTH_PREFIX + paramName]: `Bearer ${authCredential.http.credentials.token}` }; return [param, kwargs]; } } else if (authScheme instanceof HTTPBase) { if (authScheme.scheme === 'basic') { throw new Error('Basic Authentication is not supported.'); } if (authCredential.auth_type === AuthCredential_1.AuthCredentialTypes.HTTP && (!authCredential.http || !authCredential.http.credentials)) { throw new Error('Invalid HTTP auth credentials'); } } throw new Error(`Unsupported auth scheme or credential combination`); } /** * Convert a dictionary to an auth scheme */ function dictToAuthScheme(data) { if (!data.type) { throw new Error("Missing 'type' field in security scheme dictionary."); } switch (data.type) { case 'apiKey': if (!data.in || !data.name) { throw new Error('Invalid security scheme data'); } return new APIKey({ type_: AuthTypes_1.AuthSchemeType.apiKey, in_: data.in, name: data.name, }); case 'http': if (!data.scheme) { throw new Error('Invalid security scheme data'); } if (data.scheme === 'bearer') { return new HTTPBearer({ type_: AuthTypes_1.AuthSchemeType.http, scheme: data.scheme, bearerFormat: data.bearerFormat, }); } return new HTTPBase({ type_: AuthTypes_1.AuthSchemeType.http, scheme: data.scheme, }); case 'oauth2': return new OAuth2({ type_: AuthTypes_1.AuthSchemeType.oauth2, flows: data.flows || {}, }); case 'openIdConnect': if (!data.openIdConnectUrl) { throw new Error('Invalid security scheme data'); } return new OpenIdConnect({ type_: AuthTypes_1.AuthSchemeType.openIdConnect, openIdConnectUrl: data.openIdConnectUrl, }); default: throw new Error(`Invalid security scheme type: ${data.type}`); } }