feat: 更新 Gemini OAuth 流程支持新的授权方式

- 使用 codeassist.google.com 作为新的回调地址
- 实现 PKCE 认证流程增强安全性
- 更新前端授权流程指引
- 简化授权码输入流程

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
千羽
2025-08-04 00:59:57 +09:00
committed by shaw
parent 7b54f187ee
commit a80b36896d
3 changed files with 63 additions and 38 deletions

View File

@@ -77,19 +77,31 @@ function createOAuth2Client(redirectUri = null) {
);
}
// 生成授权 URL
// 生成授权 URL (支持 PKCE)
async function generateAuthUrl(state = null, redirectUri = null) {
const oAuth2Client = createOAuth2Client(redirectUri);
// 使用新的 redirect URI
const finalRedirectUri = redirectUri || 'https://codeassist.google.com/authcode';
const oAuth2Client = createOAuth2Client(finalRedirectUri);
// 生成 PKCE code verifier
const codeVerifier = await oAuth2Client.generateCodeVerifierAsync();
const stateValue = state || crypto.randomBytes(32).toString('hex');
const authUrl = oAuth2Client.generateAuthUrl({
redirect_uri: finalRedirectUri,
access_type: 'offline',
scope: OAUTH_SCOPES,
prompt: 'select_account',
state: state || uuidv4()
code_challenge_method: 'S256',
code_challenge: codeVerifier.codeChallenge,
state: stateValue,
prompt: 'select_account'
});
return {
authUrl,
state: state || authUrl.split('state=')[1].split('&')[0]
state: stateValue,
codeVerifier: codeVerifier.codeVerifier,
redirectUri: finalRedirectUri
};
}
@@ -145,12 +157,22 @@ async function pollAuthorizationStatus(sessionId, maxAttempts = 60, interval = 2
};
}
// 交换授权码获取 tokens
async function exchangeCodeForTokens(code, redirectUri = null) {
// 交换授权码获取 tokens (支持 PKCE)
async function exchangeCodeForTokens(code, redirectUri = null, codeVerifier = null) {
const oAuth2Client = createOAuth2Client(redirectUri);
try {
const { tokens } = await oAuth2Client.getToken(code);
const tokenParams = {
code: code,
redirect_uri: redirectUri
};
// 如果提供了 codeVerifier添加到参数中
if (codeVerifier) {
tokenParams.codeVerifier = codeVerifier;
}
const { tokens } = await oAuth2Client.getToken(tokenParams);
// 转换为兼容格式
return {