OAuth PKCE
将用户连接到 OpenRouter
用户可以使用 授权码交换证明密钥(Proof Key for Code Exchange,PKCE) 一键连接 OpenRouter。
以下是分步指南:
PKCE 指南
第 1 步:将用户发送到 OpenRouter
要开始 PKCE 流程,请将用户发送到 OpenRouter 的 /auth URL,并带上指向你站点的 callback_url 参数:
https://openrouter.ai/auth?callback_url=<YOUR_SITE_URL>&code_challenge=<CODE_CHALLENGE>&code_challenge_method=S256
code_challenge 参数是可选的,但建议使用。
系统会提示用户登录 OpenRouter 并授权你的应用。授权后,他们会被重定向回你的站点,URL 中带有 code 参数:
使用 SHA-256 以获得最高安全性
为获得最高安全性,将 code_challenge_method 设为 S256,并将 code_challenge 设为 code_verifier 的 sha256 哈希的 base64 编码。
更多信息请 访问 Auth0 的文档。
如何生成代码挑战
下面的示例使用 Web Crypto API 和 Buffer API 为 S256 方法生成代码挑战。你需要打包工具才能在 Web 浏览器中使用 Buffer API:
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);
Localhost 应用
任意端口 都支持 localhost 回调。这对命令行界面(CLI)工具和本地优先应用很有用,它们会绑定任意空闲的操作系统端口来接收 OAuth 回调(例如 http://localhost:51423/callback)。
Localhost 应用会被分配与主机和端口匹配的固定标题(例如 localhost:3000),但不会出现在 OpenRouter 应用市场或排行榜中。如果你想要自定义应用名称并出现在市场中,请改用公开 URL 作为回调。
进入生产环境时,请将 localhost 回调 URL 替换为公开 URL(项目网站或 GitHub 仓库链接),以获得完整的应用归因。
无界面应用(SSH 服务器、容器)
如果你的应用运行在无法访问 localhost 回调的环境中(SSH 会话、远程开发机、容器),请完全省略 callback_url:
https://openrouter.ai/auth?code_challenge=<CODE_CHALLENGE>&code_challenge_method=S256&key_label=<YOUR_APP_NAME>
用户授权后,页面会在屏幕上显示授权码,而不是重定向。用户将其复制并粘贴到你的应用中(例如在终端提示符处),然后你在第 2 步中按同样方式交换它。
此模式下 必须 提供 code_challenge:因为授权码会显示在屏幕上,PKCE 确保没有你应用的 code_verifier 的人无法使用它。该授权码一次性有效,10 分钟后过期。
第 2 步:用授权码交换由用户控制的 API 密钥
用户登录 OpenRouter 后,会被重定向回你的站点,URL 中带有 code 参数:
使用浏览器 API 提取该授权码:
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
然后用它向 https://openrouter.ai/api/v1/auth/keys 发起 API 调用,将授权码交换为由用户控制的 API 密钥:
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: '<CODE_CHALLENGE_METHOD>', // 如果使用了 code_challenge
}),
});
const { key } = await response.json();
深链接到用户的密钥
获得 API 密钥后,你可以通过 SHA-256 对密钥求哈希,创建指向用户 OpenRouter
活动页面和密钥设置页面的链接。在两个 URL 中都使用
小写十六进制摘要:
async function sha256Hex(value: string) {
const data = new TextEncoder().encode(value);
const hash = await crypto.subtle.digest('SHA-256', data);
return Array.from(new Uint8Array(hash), (byte) =>
byte.toString(16).padStart(2, '0'),
).join('');
}
const keyHash = await sha256Hex(key);
const logsUrl = `https://openrouter.ai/logs?api_key_hash=${keyHash}`;
const settingsUrl = `https://openrouter.ai/keys/${keyHash}`;
这些链接仅对已登录的 API 密钥所有者有效。如果哈希对
查看者无法解析,页面会返回 404,而不是显示
未经过滤的数据。
PKCE 流程到此结束!
第 3 步:使用 API 密钥
将 API 密钥安全地存储在用户的浏览器中或你自己的数据库中,并用它来 发起 OpenRouter 请求。
import { OpenRouter } from '@openrouter/sdk';
const openRouter = new OpenRouter({
apiKey: key, // 来自第 2 步的密钥
});
const completion = await openRouter.chat.send({
model: '~openai/gpt-latest',
messages: [
{
role: 'user',
content: '你好!',
},
],
stream: false,
});
console.log(completion.choices[0].message);
错误代码
400 Invalid code_challenge_method:确保第 1 步和第 2 步使用相同的代码挑战方法。
403 Invalid code or code_verifier:确保用户已登录 OpenRouter,并且 code_verifier 和 code_challenge_method 正确。
403 Authorization code expired:授权码在签发 10 分钟后过期。请重新开始 OAuth 流程,并尽快交换新的授权码。
405 Method Not Allowed:确保请求使用 POST 和 HTTPS。
外部工具