| Server IP : 85.155.190.233 / Your IP : 216.73.216.103 Web Server : nginx/1.24.0 System : Linux antigravity-cli 6.8.0-31-generic #31-Ubuntu SMP PREEMPT_DYNAMIC Sat Apr 20 00:40:06 UTC 2024 x86_64 User : wp-moonbloom ( 1001) PHP Version : 8.3.6 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /lib/node_modules/@google/gemini-cli/bundle/ |
Upload File : |
const require = (await import('node:module')).createRequire(import.meta.url); const __chunk_filename = (await import('node:url')).fileURLToPath(import.meta.url); const __chunk_dirname = (await import('node:path')).dirname(__chunk_filename);
import {
BaseA2AAuthProvider,
DefaultAgentCardResolver,
MCPOAuthTokenStorage,
buildAuthorizationUrl,
exchangeCodeForToken,
generatePKCEParams,
getConsentForOauth,
getPortFromUrl,
openBrowserSecurely,
refreshAccessToken,
startCallbackServer
} from "./chunk-W2MTI7FK.js";
import {
FatalCancellationError,
Storage,
coreEvents,
debugLogger,
getErrorMessage
} from "./chunk-N6QYTC2T.js";
import "./chunk-664ZODQF.js";
import "./chunk-RJTRUG2J.js";
import "./chunk-IUUIT4SU.js";
import "./chunk-34MYV7JD.js";
// packages/core/src/agents/auth-provider/oauth2-provider.ts
var OAuth2AuthProvider = class extends BaseA2AAuthProvider {
constructor(config, agentName, agentCard, agentCardUrl) {
super();
this.config = config;
this.agentName = agentName;
this.agentCardUrl = agentCardUrl;
this.tokenStorage = new MCPOAuthTokenStorage(
Storage.getA2AOAuthTokensPath(),
"gemini-cli-a2a"
);
this.authorizationUrl = config.authorization_url;
this.tokenUrl = config.token_url;
this.scopes = config.scopes;
this.mergeAgentCardDefaults(agentCard);
}
type = "oauth2";
tokenStorage;
cachedToken = null;
/** Resolved OAuth URLs — may come from config or agent card. */
authorizationUrl;
tokenUrl;
scopes;
/**
* Initialize the provider by loading any persisted token from storage.
* Also discovers OAuth URLs from the agent card if not yet resolved.
*/
async initialize() {
if ((!this.authorizationUrl || !this.tokenUrl) && this.agentCardUrl) {
await this.fetchAgentCardDefaults();
}
const credentials = await this.tokenStorage.getCredentials(this.agentName);
if (credentials && !this.tokenStorage.isTokenExpired(credentials.token)) {
this.cachedToken = credentials.token;
debugLogger.debug(
`[OAuth2AuthProvider] Loaded valid cached token for "${this.agentName}"`
);
}
}
/**
* Return an Authorization header with a valid Bearer token.
* Refreshes or triggers interactive auth as needed.
*/
async headers() {
if (this.cachedToken && !this.tokenStorage.isTokenExpired(this.cachedToken)) {
return { Authorization: `Bearer ${this.cachedToken.accessToken}` };
}
if (this.cachedToken?.refreshToken && this.tokenUrl && this.config.client_id) {
try {
const refreshed = await refreshAccessToken(
{
clientId: this.config.client_id,
clientSecret: this.config.client_secret,
scopes: this.scopes
},
this.cachedToken.refreshToken,
this.tokenUrl
);
this.cachedToken = this.toOAuthToken(
refreshed,
this.cachedToken.refreshToken
);
await this.persistToken();
return { Authorization: `Bearer ${this.cachedToken.accessToken}` };
} catch (error) {
debugLogger.debug(
`[OAuth2AuthProvider] Refresh failed, falling back to interactive flow: ${getErrorMessage(error)}`
);
await this.tokenStorage.deleteCredentials(this.agentName);
}
}
this.cachedToken = await this.authenticateInteractively();
return { Authorization: `Bearer ${this.cachedToken.accessToken}` };
}
/**
* On 401/403, clear the cached token and re-authenticate (up to MAX_AUTH_RETRIES).
*/
async shouldRetryWithHeaders(_req, res) {
if (res.status !== 401 && res.status !== 403) {
this.authRetryCount = 0;
return void 0;
}
if (this.authRetryCount >= BaseA2AAuthProvider.MAX_AUTH_RETRIES) {
return void 0;
}
this.authRetryCount++;
debugLogger.debug(
"[OAuth2AuthProvider] Auth failure, clearing token and re-authenticating"
);
this.cachedToken = null;
await this.tokenStorage.deleteCredentials(this.agentName);
return this.headers();
}
// ---------------------------------------------------------------------------
// Private helpers
// ---------------------------------------------------------------------------
/**
* Merge authorization_url, token_url, and scopes from the agent card's
* `securitySchemes` when not already provided via user config.
*/
mergeAgentCardDefaults(agentCard) {
if (!agentCard?.securitySchemes) return;
for (const scheme of Object.values(agentCard.securitySchemes)) {
if (scheme.type === "oauth2" && scheme.flows.authorizationCode) {
const flow = scheme.flows.authorizationCode;
this.authorizationUrl ??= flow.authorizationUrl;
this.tokenUrl ??= flow.tokenUrl;
this.scopes ??= Object.keys(flow.scopes);
break;
}
}
}
/**
* Fetch the agent card from `agentCardUrl` using `DefaultAgentCardResolver`
* (which normalizes proto-format cards) and extract OAuth2 URLs.
*/
async fetchAgentCardDefaults() {
if (!this.agentCardUrl) return;
try {
debugLogger.debug(
`[OAuth2AuthProvider] Fetching agent card from ${this.agentCardUrl}`
);
const resolver = new DefaultAgentCardResolver();
const card = await resolver.resolve(this.agentCardUrl, "");
this.mergeAgentCardDefaults(card);
} catch (error) {
debugLogger.warn(
`[OAuth2AuthProvider] Could not fetch agent card for OAuth URL discovery: ${getErrorMessage(error)}`
);
}
}
/**
* Run a full OAuth 2.0 Authorization Code + PKCE flow through the browser.
*/
async authenticateInteractively() {
if (!this.config.client_id) {
throw new Error(
`OAuth2 authentication for agent "${this.agentName}" requires a client_id. Add client_id to the auth config in your agent definition.`
);
}
if (!this.authorizationUrl || !this.tokenUrl) {
throw new Error(
`OAuth2 authentication for agent "${this.agentName}" requires authorization_url and token_url. Provide them in the auth config or ensure the agent card exposes an oauth2 security scheme.`
);
}
const flowConfig = {
clientId: this.config.client_id,
clientSecret: this.config.client_secret,
authorizationUrl: this.authorizationUrl,
tokenUrl: this.tokenUrl,
scopes: this.scopes
};
const pkceParams = generatePKCEParams();
const preferredPort = getPortFromUrl(flowConfig.redirectUri);
const callbackServer = startCallbackServer(pkceParams.state, preferredPort);
const redirectPort = await callbackServer.port;
const authUrl = buildAuthorizationUrl(
flowConfig,
pkceParams,
redirectPort,
/* resource= */
void 0
// No MCP resource parameter for A2A.
);
const consent = await getConsentForOauth(
`Authentication required for A2A agent: '${this.agentName}'.`
);
if (!consent) {
throw new FatalCancellationError("Authentication cancelled by user.");
}
coreEvents.emitFeedback(
"info",
`\u2192 Opening your browser for OAuth sign-in...
If the browser does not open, copy and paste this URL into your browser:
${authUrl}
\u{1F4A1} TIP: Triple-click to select the entire URL, then copy and paste it into your browser.
\u26A0\uFE0F Make sure to copy the COMPLETE URL - it may wrap across multiple lines.`
);
try {
await openBrowserSecurely(authUrl);
} catch (error) {
debugLogger.warn(
"Failed to open browser automatically:",
getErrorMessage(error)
);
}
const { code } = await callbackServer.response;
debugLogger.debug(
"\u2713 Authorization code received, exchanging for tokens..."
);
const tokenResponse = await exchangeCodeForToken(
flowConfig,
code,
pkceParams.codeVerifier,
redirectPort,
/* resource= */
void 0
);
if (!tokenResponse.access_token) {
throw new Error("No access token received from token endpoint");
}
const token = this.toOAuthToken(tokenResponse);
this.cachedToken = token;
await this.persistToken();
debugLogger.debug("\u2713 OAuth2 authentication successful! Token saved.");
return token;
}
/**
* Convert an `OAuthTokenResponse` into the internal `OAuthToken` format.
*/
toOAuthToken(response, fallbackRefreshToken) {
const token = {
accessToken: response.access_token,
tokenType: response.token_type || "Bearer",
refreshToken: response.refresh_token || fallbackRefreshToken,
scope: response.scope
};
if (response.expires_in) {
token.expiresAt = Date.now() + response.expires_in * 1e3;
}
return token;
}
/**
* Persist the current cached token to disk.
*/
async persistToken() {
if (!this.cachedToken) return;
await this.tokenStorage.saveToken(
this.agentName,
this.cachedToken,
this.config.client_id,
this.tokenUrl
);
}
};
export {
OAuth2AuthProvider
};
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/