如何使用@atproto/oauth-client-browser搭建atproto OAuth客户端回调页?
纯HTML/TypeScript环境下atproto OAuth回调页实现示例
以下是适配你需求的完整回调页实现,基于@atproto/oauth-client-browser和@atproto/api,完全采用纯HTML+TypeScript结构:
1. 回调页HTML结构(redirect.html)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>登录回调</title> <script type="module" src="./callback-handler.ts"></script> </head> <body> <p>正在处理登录,请稍候...</p> </body> </html>
2. TypeScript回调处理逻辑(callback-handler.ts)
import { createOAuthClient } from '@atproto/oauth-client-browser'; import { BskyAgent } from '@atproto/api'; // 初始化OAuth客户端 const oauthClient = createOAuthClient({ clientId: 'https://hammouda101010.github.io/turbowarp-bsky-api/static/client-metadata.json', redirectUri: 'https://hammouda101010.github.io/turbowarp-bsky-api/redirect.html', scope: 'atproto transition:generic', }); async function handleCallback() { try { // 从URL中提取授权码和状态参数 const code = new URLSearchParams(window.location.search).get('code'); const state = new URLSearchParams(window.location.search).get('state'); if (!code || !state) { throw new Error('授权参数缺失'); } // 交换授权码获取访问令牌 const tokenResponse = await oauthClient.exchangeCodeForToken(code, state); // 可选:初始化BskyAgent并设置令牌 const agent = new BskyAgent({ service: 'https://bsky.social' }); await agent.login({ accessJwt: tokenResponse.accessToken, refreshJwt: tokenResponse.refreshToken, handle: tokenResponse.idTokenClaims?.handle || '', // 从ID Token中提取用户handle }); // 向父窗口(弹窗发起页)发送登录成功信息 window.opener?.postMessage({ type: 'BSKY_LOGIN_SUCCESS', tokens: { accessToken: tokenResponse.accessToken, refreshToken: tokenResponse.refreshToken, }, userHandle: tokenResponse.idTokenClaims?.handle, }, window.origin); // 关闭回调弹窗 window.close(); } catch (err) { console.error('回调处理失败:', err); // 向父窗口发送错误信息 window.opener?.postMessage({ type: 'BSKY_LOGIN_ERROR', error: err instanceof Error ? err.message : '未知错误', }, window.origin); } } // 页面加载后立即处理回调 window.addEventListener('load', handleCallback);
关键注意事项
- DPOP令牌绑定:你的客户端元数据中开启了
dpop_bound_access_tokens,@atproto/oauth-client-browser会自动处理DPOP证明的生成与验证,无需额外编码。 - 弹窗通信安全:使用
window.postMessage时必须指定目标origin,避免跨域安全风险。 - 令牌存储:建议将获取到的令牌存储在
localStorage或会话存储中,供主应用后续调用atproto接口使用。 - 状态参数验证:
state参数用于防止CSRF攻击,客户端会自动验证其有效性,无需手动校验。
内容的提问来源于stack exchange,提问作者Hammouda101010
相关产品推荐
相关产品推荐

