Appearance
OpenRouter OAuth PKCE 授权流程允许你的应用为用户生成专属 API Key,用户只需点击一次即可完成授权。整个流程分三步:① 将用户重定向到 https://openrouter.ai/auth?callback_url=...(可选 SHA-256 code challenge)→ ② 用回调中的 code 向 POST /api/v1/auth/keys 换取用户专属 Key → ③ 用该 Key 调用 OpenRouter API。Key 由用户控制,存储在你的应用中。常见错误码:400(method 不匹配)、403(code 无效)、405(非 POST 或非 HTTPS)。
OpenRouter OAuth PKCE 允许你的应用为用户生成专属 API Key,实现用户级别的 OpenRouter 访问控制。
PKCE 授权流程
第一步:重定向用户到 OpenRouter
将用户跳转到 /auth URL,携带 callback_url 参数:
https://openrouter.ai/auth?callback_url=<YOUR_CALLBACK_URL>&code_challenge=<CODE_CHALLENGE>&code_challenge_method=S256code_challenge 参数是可选的,但推荐使用以提升安全性。
用户登录 OpenRouter 并授权你的应用后,会被重定向回你的 callback_url,URL 中带有 code 参数。
使用 SHA-256 最大化安全性
将 code_challenge_method 设为 S256,code_challenge 设为 code_verifier 的 SHA-256 哈希的 base64url 编码。
生成 Code Challenge
typescript
import { Buffer } from 'buffer';
async function createSHA256CodeChallenge(input: string) {
const encoder = new TextEncoder();
const data = encoder.encode(input);
const hash = await crypto.subtle.digest('SHA-256', data);
return Buffer.from(hash).toString('base64url');
}
const codeVerifier = 'your-random-string';
const generatedCodeChallenge = await createSHA256CodeChallenge(codeVerifier);本地应用
如果应用没有公网 URL,测试时可以用 http://localhost:3000 作为 callback 和 referrer URL。上线时替换为公网 URL 或 GitHub 仓库链接。
第二步:用 code 换取用户专属 API Key
从 URL 中提取 code:
javascript
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');调用 /api/v1/auth/keys 兑换 API Key:
javascript
const response = await fetch('https://openrouter.ai/api/v1/auth/keys', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
code: '<CODE_FROM_QUERY_PARAM>',
code_verifier: '<CODE_VERIFIER>', // 如果使用了 code_challenge
code_challenge_method: '<METHOD>', // 如果使用了 code_challenge
}),
});
const { key } = await response.json();第三步:使用 API Key
将 Key 安全存储在用户浏览器或你的数据库中,然后用它调用 OpenRouter:
typescript
import { OpenRouter } from '@openrouter/sdk';
const openRouter = new OpenRouter({
apiKey: key, // 第二步获取的 Key
});
const completion = await openRouter.chat.send({
model: 'openai/gpt-5.2',
messages: [
{
role: 'user',
content: 'Hello!',
},
],
stream: false,
});
console.log(completion.choices[0].message);错误码
| 错误码 | 说明 | 解决方法 |
|---|---|---|
400 Invalid code_challenge_method | 第一步和第二步使用了不同的 method | 确保两步使用相同的 code_challenge_method |
403 Invalid code or code_verifier | code 无效或 code_verifier 不匹配 | 确认用户已登录 OpenRouter,检查 code_verifier 和 code_challenge_method |
405 Method Not Allowed | 请求方法或协议错误 | 使用 POST 方法和 HTTPS 协议 |
常见问题
Q: 用户的 API Key 和我的应用 Key 是同一个吗?
A: 不是。通过 PKCE 流程获取的 Key 是用户专属的,关联到该用户的 OpenRouter 账户,消费的是用户自己的 credits(或用户授权你的应用使用的 credits)。你的应用自身的 Key 是独立的。
Q: 这个 Key 有什么权限?
A: 用户通过授权流程生成的 Key 具有该用户的完整权限——可以调用所有模型、查看用量等,等同于用户在 OpenRouter 控制台手动创建的 Key。
Q: code_challenge 是必须的吗?
A: 不是强制要求,但强烈推荐。省略 code_challenge 时流程仍然有效,但安全性较低——存在 authorization code 被截获的风险。有条件的话始终加上 S256 challenge。