@mondaydotcomorg/atp-protocol
Version:
Core protocol types and interfaces for Agent Tool Protocol
202 lines • 7.26 kB
JavaScript
/**
* Authentication and credential management types for Agent Tool Protocol
*/
/**
* Credential resolver - resolves auth config to actual credentials
*/
export class CredentialResolver {
providers = new Map();
/**
* Registers a runtime credential provider
*/
registerProvider(provider) {
this.providers.set(provider.name, provider);
}
/**
* Resolves auth configuration to credentials
*/
async resolve(authConfig) {
if (authConfig.provider) {
const provider = this.providers.get(authConfig.provider);
if (!provider) {
throw new Error(`Credential provider '${authConfig.provider}' not found`);
}
return await provider.resolve();
}
switch (authConfig.scheme) {
case 'apiKey':
return this.resolveAPIKey(authConfig);
case 'bearer':
return this.resolveBearer(authConfig);
case 'basic':
return this.resolveBasic(authConfig);
case 'oauth2':
return this.resolveOAuth2(authConfig);
case 'custom':
return this.resolveCustom(authConfig);
case 'composite':
return this.resolveComposite(authConfig);
default:
throw new Error(`Unsupported auth scheme: ${authConfig.scheme}`);
}
}
resolveAPIKey(config) {
const value = this.getValue(config);
if (!value) {
throw new Error(`API key not provided for '${config.name}'`);
}
if (config.in === 'header') {
return { headers: { [config.name]: value } };
}
else {
return { queryParams: { [config.name]: value } };
}
}
resolveBearer(config) {
const token = this.getValue(config);
if (!token) {
throw new Error('Bearer token not provided');
}
return {
headers: {
Authorization: `Bearer ${token}`,
},
};
}
resolveBasic(config) {
const username = config.usernameEnvVar ? process.env[config.usernameEnvVar] : config.username;
const password = config.passwordEnvVar
? process.env[config.passwordEnvVar]
: this.getValue(config);
if (!username || !password) {
throw new Error('Basic auth username and password not provided');
}
const credentials = Buffer.from(`${username}:${password}`).toString('base64');
return {
headers: {
Authorization: `Basic ${credentials}`,
},
};
}
async resolveOAuth2(config) {
const clientId = config.clientIdEnvVar ? process.env[config.clientIdEnvVar] : config.clientId;
const clientSecret = config.clientSecretEnvVar
? process.env[config.clientSecretEnvVar]
: undefined;
if (!clientId || !clientSecret) {
throw new Error('OAuth2 client credentials not provided');
}
if (config.flow === 'clientCredentials') {
const token = await this.fetchOAuth2Token(config.tokenUrl, clientId, clientSecret, config.scopes);
return {
headers: {
Authorization: `Bearer ${token}`,
},
};
}
const token = this.getValue(config);
if (token) {
return {
headers: {
Authorization: `Bearer ${token}`,
},
};
}
throw new Error(`OAuth2 flow '${config.flow}' requires manual token setup`);
}
resolveCustom(config) {
const headers = {};
const queryParams = {};
Object.assign(headers, config.headers);
if (config.headerEnvVars) {
for (const [headerName, envVar] of Object.entries(config.headerEnvVars)) {
const value = process.env[envVar];
if (value) {
headers[headerName] = value;
}
}
}
if (config.queryParams) {
Object.assign(queryParams, config.queryParams);
}
if (config.queryParamEnvVars) {
for (const [paramName, envVar] of Object.entries(config.queryParamEnvVars)) {
const value = process.env[envVar];
if (value) {
queryParams[paramName] = value;
}
}
}
return {
headers: Object.keys(headers).length > 0 ? headers : undefined,
queryParams: Object.keys(queryParams).length > 0 ? queryParams : undefined,
};
}
resolveComposite(config) {
const headers = {};
const queryParams = {};
for (const [credName, credConfig] of Object.entries(config.credentials)) {
const value = credConfig.envVar ? process.env[credConfig.envVar] : credConfig.value;
if (!value) {
if (credConfig.required !== false) {
throw new Error(`Required credential '${credName}' not provided`);
}
continue;
}
const injectAs = config.injectAs || 'header';
if ((injectAs === 'header' || injectAs === 'both') && credConfig.headerName) {
headers[credConfig.headerName] = value;
}
if ((injectAs === 'query' || injectAs === 'both') && credConfig.queryParamName) {
queryParams[credConfig.queryParamName] = value;
}
if (!credConfig.headerName && !credConfig.queryParamName) {
if (injectAs === 'query' || injectAs === 'both') {
queryParams[credName] = value;
}
else {
headers[`X-${credName}`] = value;
}
}
}
return {
headers: Object.keys(headers).length > 0 ? headers : undefined,
queryParams: Object.keys(queryParams).length > 0 ? queryParams : undefined,
};
}
/**
* Gets credential value from config (env var or direct value)
*/
getValue(config) {
if (config.envVar) {
return process.env[config.envVar];
}
return config.value;
}
/**
* Fetches OAuth2 token using client credentials flow
*/
async fetchOAuth2Token(tokenUrl, clientId, clientSecret, scopes) {
const params = new URLSearchParams({
grant_type: 'client_credentials',
client_id: clientId,
client_secret: clientSecret,
});
if (scopes && scopes.length > 0) {
params.append('scope', scopes.join(' '));
}
const response = await fetch(tokenUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params.toString(),
});
if (!response.ok) {
throw new Error(`OAuth2 token fetch failed: ${response.statusText}`);
}
const data = (await response.json());
return data.access_token;
}
}
//# sourceMappingURL=auth.js.map