UNPKG

adk-typescript

Version:

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

199 lines (198 loc) 7.97 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AuthHandler = void 0; const AuthCredential_1 = require("./AuthCredential"); const AuthSchemes_1 = require("./AuthSchemes"); // Helper: deep copy an object function deepCopy(obj) { return JSON.parse(JSON.stringify(obj)); } // Helper: hash an object (for keying) function hashObject(obj) { const str = JSON.stringify(obj); let hash = 0, i, chr; if (str.length === 0) return hash; for (i = 0; i < str.length; i++) { chr = str.charCodeAt(i); hash = ((hash << 5) - hash) + chr; hash |= 0; } return hash; } class AuthHandler { constructor(authConfig) { this.authConfig = authConfig; } /** * Exchanges an auth token from the authorization response. * Returns an AuthCredential object containing the access token. */ exchangeAuthToken() { // This is a placeholder for actual OAuth2 token exchange logic. // In a real implementation, use a library like 'simple-oauth2' or 'openid-client'. // Here, we just return the exchanged credential if present. const cred = this.authConfig.exchangedAuthCredential; return cred == null ? undefined : cred; } /** * Parses and stores the auth response in the state. */ parseAndStoreAuthResponse(state) { const credentialKey = this.getCredentialKey(); state[credentialKey] = this.authConfig.exchangedAuthCredential; const scheme = this.authConfig.authScheme; if (!scheme || !('type' in scheme)) return; if (scheme.type !== AuthSchemes_1.AuthSchemeType.OAUTH2 && scheme.type !== AuthSchemes_1.AuthSchemeType.OPEN_ID_CONNECT) return; state[credentialKey] = this.exchangeAuthToken(); } /** * Validates the handler's configuration. */ _validate() { if (!this.authConfig.authScheme) { throw new Error('auth_scheme is empty.'); } } /** * Retrieves the auth response from the state. */ getAuthResponse(state) { const credentialKey = this.getCredentialKey(); const cred = state[credentialKey]; if (cred === null || cred === undefined) { return undefined; } return cred; } /** * Generates an auth request, possibly generating an auth URI if needed. */ generateAuthRequest() { const scheme = this.authConfig.authScheme; if (!scheme || !('type' in scheme)) return deepCopy(this.authConfig); if (scheme.type !== AuthSchemes_1.AuthSchemeType.OAUTH2 && scheme.type !== AuthSchemes_1.AuthSchemeType.OPEN_ID_CONNECT) return deepCopy(this.authConfig); // auth_uri already in exchanged credential if (this.authConfig.exchangedAuthCredential && this.authConfig.exchangedAuthCredential.oauth2 && this.authConfig.exchangedAuthCredential.oauth2.auth_uri) { return deepCopy(this.authConfig); } // Check if raw_auth_credential exists if (!this.authConfig.rawAuthCredential) { throw new Error(`Auth Scheme ${scheme.type} requires auth_credential.`); } // Check if oauth2 exists in raw_auth_credential if (!this.authConfig.rawAuthCredential.oauth2) { throw new Error(`Auth Scheme ${scheme.type} requires oauth2 in auth_credential.`); } // auth_uri in raw credential if (this.authConfig.rawAuthCredential.oauth2.auth_uri) { return { authScheme: scheme, rawAuthCredential: this.authConfig.rawAuthCredential, exchangedAuthCredential: deepCopy(this.authConfig.rawAuthCredential), }; } // Check for client_id and client_secret if (!this.authConfig.rawAuthCredential.oauth2.client_id || !this.authConfig.rawAuthCredential.oauth2.client_secret) { throw new Error(`Auth Scheme ${scheme.type} requires both client_id and client_secret in auth_credential.oauth2.`); } // Generate new auth URI const exchangedCredential = this.generateAuthUri(); return { authScheme: scheme, rawAuthCredential: this.authConfig.rawAuthCredential, exchangedAuthCredential: exchangedCredential, }; } /** * Generates a unique key for the given auth scheme and credential. */ getCredentialKey() { let authScheme = this.authConfig.authScheme; let authCredential = this.authConfig.rawAuthCredential; // Remove extra fields if present if (authScheme && 'modelExtra' in authScheme) { authScheme = { ...authScheme }; delete authScheme.modelExtra; } const schemeName = authScheme ? `${authScheme.type}_${hashObject(authScheme)}` : ''; if (authCredential && 'modelExtra' in authCredential) { authCredential = { ...authCredential }; delete authCredential.modelExtra; } const credentialName = authCredential ? `${authCredential.auth_type}_${hashObject(authCredential)}` : ''; return `temp:adk_${schemeName}_${credentialName}`; } /** * Generates an OAuth2 authorization URI. */ generateAuthUri() { const scheme = this.authConfig.authScheme; const credential = this.authConfig.rawAuthCredential; let authorizationEndpoint = ''; let scopes = []; if (scheme && 'authorization_endpoint' in scheme) { authorizationEndpoint = scheme.authorization_endpoint; scopes = scheme.scopes || []; } else if (scheme && 'flows' in scheme) { const flows = scheme.flows; if (flows.implicit && flows.implicit.authorizationUrl) { authorizationEndpoint = flows.implicit.authorizationUrl; scopes = Object.keys(flows.implicit.scopes || {}); } else if (flows.authorizationCode && flows.authorizationCode.authorizationUrl) { authorizationEndpoint = flows.authorizationCode.authorizationUrl; scopes = Object.keys(flows.authorizationCode.scopes || {}); } else if (flows.clientCredentials && flows.clientCredentials.tokenUrl) { authorizationEndpoint = flows.clientCredentials.tokenUrl; scopes = Object.keys(flows.clientCredentials.scopes || {}); } else if (flows.password && flows.password.tokenUrl) { authorizationEndpoint = flows.password.tokenUrl; scopes = Object.keys(flows.password.scopes || {}); } } if (!authorizationEndpoint) { throw new Error('Authorization endpoint is not configured in the auth scheme.'); } // Ensure credential and credential.oauth2 are present if (!credential || !credential.oauth2) { throw new Error('Raw auth credential and oauth2 must be provided to generate auth URI.'); } // Generate a random state string const state = Math.random().toString(36).substring(2); // Build the auth URI const params = new URLSearchParams({ response_type: 'code', client_id: credential.oauth2.client_id || '', redirect_uri: credential.oauth2.redirect_uri || '', scope: scopes.join(' '), state, }); const authUri = `${authorizationEndpoint}?${params.toString()}`; return { auth_type: AuthCredential_1.AuthCredentialTypes.OAUTH2, oauth2: { ...credential.oauth2, auth_uri: authUri, state, }, }; } } exports.AuthHandler = AuthHandler;