Skip to content

OpenRouter OAuth PKCE 授权流程允许你的应用为用户生成专属 API Key,用户只需点击一次即可完成授权。整个流程分三步:① 将用户重定向到 https://openrouter.ai/auth?callback_url=...(可选 SHA-256 code challenge)→ ② 用回调中的 codePOST /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=S256

code_challenge 参数是可选的,但推荐使用以提升安全性。

用户登录 OpenRouter 并授权你的应用后,会被重定向回你的 callback_url,URL 中带有 code 参数。

使用 SHA-256 最大化安全性

code_challenge_method 设为 S256code_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_verifiercode 无效或 code_verifier 不匹配确认用户已登录 OpenRouter,检查 code_verifiercode_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。