关于 oauth-integrations
面向边缘运行时的 GitHub 与 Microsoft OAuth 实现指南,适用于在 Cloudflare Workers 等环境中构建身份验证的开发者。内容聚焦运行时限制、必需请求参数、令牌流程及常见错误处理。
主要功能
- 01GitHub OAuth 请求与令牌交换
- 02处理 GitHub 私有邮箱
- 03Microsoft Entra 手动 OAuth 流程
- 04配置 Microsoft Graph 所需范围
- 05说明租户选项与令牌生命周期
适用场景
- 01在 Cloudflare Workers 中接入 GitHub 登录
- 02从 Microsoft Graph 获取用户资料
- 03为长会话实现刷新令牌流程
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ jezweb/ claude-skills --skill oauth-integrations安装后在 Claude Code 中输入/oauth-integrations确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
README.md.claude-plugin/plugin.jsonrules/github-oauth.mdmicrosoft-oauth.md详细介绍
边缘环境的 OAuth 集成
在 Cloudflare Workers 和其他边缘运行时中实现 GitHub 和 Microsoft OAuth。
GitHub OAuth
必需的请求头
GitHub API 的要求十分严格,与其他提供商不同。
| 请求头 | 要求 |
|---|---|
User-Agent | 必需——缺少此项会返回 403 |
Accept | 建议使用 application/vnd.github+json |
const resp = await fetch('https://api.github.com/user', {
headers: {
Authorization: `Bearer ${accessToken}`,
'User-Agent': 'MyApp/1.0', // Required!
'Accept': 'application/vnd.github+json',
},
});
私有邮箱处理
GitHub 用户可以将邮箱设为私有(/user 返回 email: null)。
if (!userData.email) {
const emails = await fetch('https://api.github.com/user/emails', { headers })
.then(r => r.json());
userData.email = emails.find(e => e.primary && e.verified)?.email;
}
需要 user:email scope。
令牌交换
默认情况下,令牌交换会返回表单编码的数据。添加 Accept 请求头以获取 JSON:
const tokenResponse = await fetch('https://github.com/login/oauth/access_token', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json', // Get JSON response
},
body: new URLSearchParams({ code, client_id, client_secret, redirect_uri }),
});
GitHub OAuth 注意事项
| 问题 | 解决方案 |
|---|---|
| 回调 URL | 必须完全匹配——不支持通配符或子目录匹配 |
| 令牌交换返回表单编码的数据 | 添加 'Accept': 'application/json' 请求头 |
| 令牌不会过期 | 无需刷新流程,但令牌被撤销后必须完整重新认证 |
Microsoft Entra(Azure AD)OAuth
MSAL 为什么无法在 Workers 中运行
MSAL.js 依赖于:
- 浏览器 API(localStorage、sessionStorage、DOM)
- Node.js crypto 模块
Cloudflare 的 V8 隔离运行时两者都不支持。请改用手动 OAuth:
- 手动构建 OAuth URL
- 通过 fetch 直接交换令牌
- 使用
jose库验证 JWT
必需的作用域
// For user identity (email, name, profile picture)
const scope = 'openid email profile User.Read';
// For refresh tokens (long-lived sessions)
const scope = 'openid email profile User.Read offline_access';
重要:Microsoft Graph /me 端点需要 User.Read。如果缺少此作用域,令牌交换会成功,但获取用户信息时会返回 403。
用户信息端点
// Microsoft Graph /me endpoint
const resp = await fetch('https://graph.microsoft.com/v1.0/me', {
headers: { Authorization: `Bearer ${accessToken}` },
});
// Email may be in different fields
const email = data.mail || data.userPrincipalName;
租户配置
| 租户值 | 可登录的用户 |
|---|---|
common | 任何 Microsoft 账户(个人账户和工作账户) |
organizations | 仅限工作或学校账户 |
consumers | 仅限个人 Microsoft 账户 |
{tenant-id} | 仅限特定组织 |
Azure 门户设置
- 应用注册 → 新注册
- 平台:选择 Web(而非 SPA),用于服务器端 OAuth
- 重定向 URI:添加
/callback和/admin/callback - 证书和机密 → 新建客户端密钥
令牌有效期
| 令牌类型 | 默认有效期 | 备注 |
|---|---|---|
| 访问令牌 | 60-90 分钟 | 可通过令牌有效期策略配置 |
| 刷新令牌 | 90 天 | 更改密码后会被撤销 |
| ID 令牌 | 60 分钟 | 与访问令牌相同 |
最佳实践:始终请求 offline_access scope,并为时长超过 1 小时的会话实现刷新令牌流程。
常见修正
| 如果 Claude 建议…… | 请改为…… |
|---|---|
| 在 GitHub fetch 请求中不添加 User-Agent | 添加 'User-Agent': 'AppName/1.0'(必需) |
| 在 Workers 中使用 MSAL.js | 使用手动 OAuth + jose 验证 JWT |
| Microsoft scope 不包含 User.Read | 添加 User.Read scope |
| 只从令牌声明中获取邮箱 | 使用 Graph /me 端点 |
错误参考
GitHub 错误
| 错误 | 原因 | 修复方法 |
|---|---|---|
| 403 Forbidden | 缺少 User-Agent 请求头 | 添加 User-Agent 请求头 |
email: null | 用户邮箱设为私有 | 使用 user:email scope 获取 /user/emails |
Microsoft 错误
| 错误 | 原因 | 修复方法 |
|---|---|---|
| AADSTS50058 | 静默认证失败 | 使用交互式流程 |
| AADSTS700084 | 刷新令牌已过期 | 重新认证用户 |
| Graph /me 返回 403 | 缺少 User.Read scope | 将 User.Read 添加到 scope 中 |
参考资料
- GitHub API:https://docs.github.com/en/rest
- GitHub OAuth:https://docs.github.com/en/apps/oauth-apps
- Microsoft Graph 权限:https://learn.microsoft.com/en-us/graph/permissions-reference
- AADSTS 错误代码:https://learn.microsoft.com/en-us/entra/identity-platform/reference-error-codes
评论
支持 Markdown