adk-typescript
Version:
TypeScript port of Google's Agent Development Kit (ADK)
325 lines (324 loc) • 11.7 kB
JavaScript
;
/**
* 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}`);
}
}