章节导航
OAuth PKCE
OAuth PKCE
OAuth 2.0 PKCE(Proof Key for Code Exchange)让公开用户端应用程式(浏览器 SPA、行动 App)能够代表个别用户呼叫 API,无需在用户端储存长效的伺服器密钥。
何时使用 OAuth PKCE
- 建构需要每位用户计费的浏览器 SPA 或行动 App
- 多租户 SaaS — 每位终端用户支付自己的 API 使用费用
- 无法在用户端储存共用密钥(公开用户端)
- 需要每位用户各自独立、可撤销的密钥(不会自动过期),而非单一共用 API 密钥
你的用户会看到什么
请在你自己的登录界面向用户说明这些步骤:
- 在你的应用内选择“使用 BazaarLink 登录”(或你自己命名的按钮)。
- 浏览器打开 BazaarLink 授权页。若尚未登录,会先登录,登录后自动回到这一页。
- 页面会显示你的应用网址,以及允许后会发生的事:为该应用创建一把新的 API 密钥、用量从 BazaarLink 余额扣款、可随时撤销。用户可为密钥命名并设置每月额度上限(均为选填)。
- 点击“允许”后回到你的应用;点击“拒绝”则不会创建密钥、你的应用也不会收到通知,用户会看到“已拒绝访问”页面。
- 之后若要撤销,打开“API 密钥”页面(https://bazaarlink.ai/keys),停用或删除以你的应用命名的那把密钥。
工作方式
步骤 1 — 发起认证 — 产生随机的 code_verifier(长随机字串)及其 SHA-256 杂凑值作为 code_challenge,然后将用户重新导向至 BazaarLink 认证页面。
https://bazaarlink.ai/auth?callback_url=https://yourapp.com/callback&code_challenge=CODE_CHALLENGE&code_challenge_method=S256授权网址参数
- callback_url(必填)— 用户点击允许后回到的网址,规则见下方。
- code_challenge(必填)— code_verifier 的 SHA-256 再做 base64url 编码(43 字符,不含 = 补位)。
- code_challenge_method(必填)— 必须是 S256。
- state(选填)— 你自己的不透明防 CSRF 值,1 到 256 个可见 ASCII 字符。BazaarLink 会原样在授权码之后以 &state=… 带回。格式不正确的 state 会让授权页显示“授权请求无效”。
- key_label(选填)— 最多 100 个字符。会预填授权页的密钥名称(用户仍可修改)。过长或空白的标签会被忽略。
- 无回调的工具(CLI/桌面程序)— 省略 callback_url。用户允许后,页面会显示一次性授权码(5 分钟内有效、只能用一次),让用户输入到你的工具;换 key 的方式与跳转得到的授权码完全相同。页面无法显示是哪个应用在请求,请提醒用户只在自己启动的工具里输入。
不支持
- workspace_id 与 required_workspace_id — 不支持。密钥一律属于用户自己的账号。
- code_challenge_method=plain — 不支持(只收 S256)。
callback_url 规则
- 必须是 https://。http:// 只接受 localhost、127.0.0.1 与 [::1](任何端口),此时授权页会显示本机开发警告。
- 不可含片段(#),网址内不可含账号密码,最长 2048 字符。
- 授权页会显示你的 callback 主机名,让用户看得出是哪个应用在请求授权。
- 用户点击允许后,浏览器会被重定向到你的 callback_url 并附上 code=…(若你有带 state,也会附上 state=…;既有的查询字符串会保留)。授权码 10 分钟内有效且只能使用一次。
步骤 2 — 交换授权码取得 API 密钥 — 用户授权后,BazaarLink 会将用户重定向到您的 callback_url 并附上一次性授权码。授权码 10 分钟内有效且只能使用一次;code_verifier 错误会让它立刻作废。请 POST code、code_verifier 与 code_challenge_method(三者均必填),即可获取该用户的 API 密钥。
步骤 3 — 使用用户专属密钥 — 返回的密钥是普通的 BazaarLink API 密钥,属于授权的那位用户 — 用量从该用户的余额扣款,不会算在你头上。
curl https://bazaarlink.ai/api/v1/chat/completions \
-H "Authorization: Bearer sk-bl-..." \
-H "Content-Type: application/json" \
-d '{"model": "google/gemini-3.5-flash", "messages": [{"role": "user", "content": "Hello"}]}'JavaScript 示例(浏览器)
/auth 页面与 POST /api/v1/auth/keys 由 https://bazaarlink.ai 提供(不是 api.bazaarlink.ai)。获取的密钥在 https://bazaarlink.ai/api/v1 与 https://api.bazaarlink.ai/v1 两个 base URL 上都可使用。
若用户在授权时设置额度上限,该上限为每月额度,按账号的月周期重置。
错误
错误格式为 OpenAI 风格 {"error":{"message","type","code"}}。POST /api/v1/auth/keys 可能返回:
- 400 invalid_code_challenge_method — 未带 code_challenge_method、为 plain,或不是 S256。
- 400 — JSON 内容无效,或缺少 code/code_verifier。
- 403 invalid_code — 授权码不存在、已过期或已使用、code_verifier 错误,或该账号已不被允许。以上情况刻意返回相同信息,调用方无法区分。code_verifier 错误也会让授权码作废:请用户重新授权。
- 429 rate_limited — 同一 IP 10 分钟内交换超过 30 次(见 Retry-After 标头)。
- 429 key_total_cap — 该账号已持有 200 把 API 密钥的上限。
- 405 — 只接受 POST。
从你的服务器创建授权码(管理密钥)
个人管理密钥(Management Key)的拥有者可以不经过浏览器授权页,直接用 POST /api/v1/auth/keys/code 创建授权码(与 OpenRouter 兼容)。授权码会绑定该管理密钥的拥有者,因此交换到的是该拥有者账号下的标准密钥,额度、周期、到期时间与名称都由这里决定。适用于你自己的工具已持有管理密钥、想替某个 App 发一把受限密钥的情况。交换步骤(POST /api/v1/auth/keys)与上面相同。
- callback_url(必填)与 code_challenge + code_challenge_method=S256(必填)— 规则与授权网址相同。
- key_label(选填)— 最多 100 个字符,密钥名称。默认为“App: <你的 callback 主机名>”。
- limit(选填)— 美元额度上限,0 或以上;0 或未带代表不限额。
- usage_limit_type(选填)— daily、weekly 或 monthly:额度多久重置一次。只在有 limit 时生效;默认 monthly。
- expires_at(选填)— 密钥到期时间:未来的 ISO 8601 UTC 时间且须含秒,例如 2026-12-31T23:59:59Z。只到分钟的格式会被拒绝。未带代表密钥一直有效,直到被撤销。
- workspace_id — 不支持(400)。spawn_agent 与 spawn_cloud 会被接受但忽略。
响应:{ "data": { "id", "app_id", "created_at" } }。id 就是要拿去交换的一次性授权码(10 分钟内有效、只能用一次)。BazaarLink 没有 App 注册机制,app_id 是由你的 callback 地址推导出的固定整数:同一地址永远得到相同的 app_id。
- 401 unauthorized — 没带 Bearer 密钥,或密钥不存在。
- 403 management_key_required — 该密钥不是个人管理密钥(标准密钥与组织管理密钥都会被拒绝)。
- 403 account_not_allowed — 该密钥的拥有者已被停权或删除。
- 400 — invalid_callback_url、invalid_code_challenge_method、invalid_code_challenge、invalid_expires_at、workspace_not_supported,或内容格式错误。
- 429 rate_limited — 同一拥有者每小时超过 30 个授权码,或同一 IP 每小时超过 120 个(见 Retry-After)。
你拿到的密钥
- 一把标准的 BazaarLink API 密钥(sk-bl-…),与在“API 密钥”页面创建的相同,不会自动过期。
- 用量从用户的 BazaarLink 余额扣款。若用户在授权页设置额度上限,该上限为每月额度。
- 两个 base URL 都可使用:https://bazaarlink.ai/api/v1 与 https://api.bazaarlink.ai/v1。
- 会计入账号 200 把密钥的上限,并出现在用户的“API 密钥”列表中,用户可随时停用或删除。
- 被停权或已删除的账号无法授权应用;停权前发出的授权码在交换时会被拒绝(403 invalid_code)。
你会得到什么
- 授权码 + PKCE 流程(公开用户端应用程式)
- 每用户计费:各用户用自己的余额支付自己的用量
- 每位用户一把独立密钥,列在该用户的“API 密钥”页面,用户可随时撤销