集成 · 用 Pikeway 登录

「用 Pikeway 登录」接入步骤

标准的 OAuth 2.1 授权码流程,带 PKCE 和动态客户端注册。只支持公共客户端:没有 client secret。拿到的 access token 是一把属于用户、有预算上限的 Pikeway key。

在做 MCP 客户端?可能不需要手动实现这些。把它指向 https://gw.pikeway.ai/mcp/agent:不带 token 时会返回 401 和 WWW-Authenticate: Bearer resource_metadata=… 挑战,MCP SDK 会自动走完下面整个流程。
1

读取授权服务器元数据

所有端点都发布在授权服务器元数据(RFC 8414)中。同一份文档也在 /.well-known/openid-configuration 提供,方便只查这个地址的库。请从元数据读取端点,而不是写死在代码里。

GET/.well-known/oauth-authorization-server
bash
curl https://gw.pikeway.ai/.well-known/oauth-authorization-server
响应
{
  "issuer": "https://gw.pikeway.ai",
  "authorization_endpoint": "/oauth/authorize",
  "token_endpoint": "https://gw.pikeway.ai/api/mcp-oauth/token",
  "registration_endpoint": "https://gw.pikeway.ai/api/mcp-oauth/register",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "code_challenge_methods_supported": ["S256"],
  "token_endpoint_auth_methods_supported": ["none"],
  "scopes_supported": ["pikeway"]
}

只有一个 scope:pikeway。请求中可以省略 scope。

2

注册你的应用

注册一次即可(RFC 7591 动态客户端注册,无需账户或审核),把 client_id 存进配置。只有重定向地址变化时才需要重新注册。

POST/api/mcp-oauth/register
Body(JSON)
redirect_urisstring[]必填
1 到 10 个地址,不能带 fragment。https:// 不限;http:// 只允许 localhost、127.0.0.1 或 [::1];桌面应用可用自定义 scheme(myapp://callback),但 javascript:、data:、file: 等除外。授权时的地址必须与其中之一完全一致。
client_namestring
显示在授权页上,也用来命名用户的 key(MCP · client_name)。最多 100 个字符,请使用你的产品名。
token_endpoint_auth_methodstring
只支持 none(带 PKCE 的公共客户端)。其他值会被拒绝,返回 invalid_client_metadata。
bash
curl -X POST https://gw.pikeway.ai/api/mcp-oauth/register \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "Acme Research",
    "redirect_uris": ["https://acme.example/pikeway/callback", "http://localhost:3000/pikeway/callback"]
  }'
响应
HTTP/1.1 201 Created
Cache-Control: no-store

{
  "client_id": "mcp_Xr4k9pQ2vL8sT1wZb7nYdA3e",
  "client_name": "Acme Research",
  "redirect_uris": ["https://acme.example/pikeway/callback", "http://localhost:3000/pikeway/callback"],
  "client_id_issued_at": 1792834800,
  "grant_types": ["authorization_code", "refresh_token"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}
3

把用户引导到授权页

每次登录都生成新的 PKCE verifier 和 state,保存在用户的服务端会话中,然后把浏览器重定向到授权端点。必须使用 S256 方式的 PKCE。

GET/oauth/authorize
查询参数
response_typestring必填
固定为 code。
client_idstring必填
第 2 步拿到的值。
redirect_uristring必填
与注册的某个地址完全一致。
code_challengestring必填
base64url(sha256(verifier)),不带填充:43 个字符。
code_challenge_methodstring必填
固定为 S256;不接受 plain。
statestring
随机值,会在跳回时原样带回。协议上可选,但请务必发送并校验。
javascript
import { createHash, randomBytes } from "node:crypto";

// 1. A fresh PKCE verifier and state for every sign-in
const verifier = randomBytes(32).toString("base64url");            // 43 chars
const challenge = createHash("sha256").update(verifier).digest("base64url");
const state = randomBytes(16).toString("base64url");
// Keep verifier + state in the user's server-side session
session.pikeway = { verifier, state };

// 2. Redirect the browser
const url = new URL("/oauth/authorize");
url.search = new URLSearchParams({
  response_type: "code",
  client_id: process.env.PIKEWAY_CLIENT_ID,
  redirect_uri: "https://acme.example/pikeway/callback",
  code_challenge: challenge,
  code_challenge_method: "S256",
  state,
}).toString();
return Response.redirect(url, 302);

未登录的用户会先跳到 Pikeway 登录页,登录后直接回到授权页。授权页会显示你的应用名称、它能做什么、将跳回的主机名,以及消费上限选择($1、$5、$20、$100 或不限;默认选中 $5)。

4

处理回调

用户做出选择后,浏览器会带着你的 state 以及 code 或 error 跳到你的 redirect_uri:

已允许
https://acme.example/pikeway/callback?code=SplxlOBeZQQYbYS6WxSbIA…&state=af0ifjsldkj
已拒绝
https://acme.example/pikeway/callback?state=af0ifjsldkj&error=access_denied
  • 如果 state 和你保存的不一致,拒绝这个请求。
  • error=access_denied:用户点了「拒绝」。error=invalid_request:PKCE 参数缺失或格式不对。
  • code 有效期 10 分钟,只能使用一次。请立即兑换。
5

用 code 换取 token

从服务端调用令牌端点,支持 application/x-www-form-urlencoded 或 JSON。

POST/api/mcp-oauth/token
Body
grant_typestring必填
authorization_code
codestring必填
回调中拿到的 code。
code_verifierstring必填
第 3 步生成的 verifier。
redirect_uristring必填
必须与第 3 步使用的一致。
client_idstring
建议发送。如果发送,必须与签发 code 的客户端一致。
bash
curl -X POST https://gw.pikeway.ai/api/mcp-oauth/token \
  -d grant_type=authorization_code \
  -d code=SplxlOBeZQQYbYS6WxSbIA… \
  -d code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk \
  -d client_id=mcp_Xr4k9pQ2vL8sT1wZb7nYdA3e \
  -d redirect_uri=https://acme.example/pikeway/callback
响应
HTTP/1.1 200 OK
Cache-Control: no-store

{
  "access_token": "pk-…",
  "token_type": "Bearer",
  "expires_in": 2592000,
  "refresh_token": "pkr-…",
  "scope": "pikeway"
}
access_tokenpk-…
一把属于用户、受其所选预算约束的 Pikeway key。有效期 30 天。
refresh_tokenpkr-…
一次性使用。在 access token 过期前用它换一对新的 token。
expires_inseconds
2592000(30 天)。
6

以用户身份调用 API

access token 的用法与其他 Pikeway key 完全一样。先用 /v1/auth/whoami 显示是谁连接的,再用 /v1/wallet/balance 显示他能花多少。

GET/v1/auth/whoami
bash
curl https://gw.pikeway.ai/v1/auth/whoami -H "Authorization: Bearer $ACCESS_TOKEN"
响应
{
  "userId": "cm2x8k1qz0000abcd1234efgh",
  "email": "[email protected]",
  "walletAddress": null,
  "twitterHandle": null,
  "key": {
    "id": "cm2x8m3rt0001abcd5678ijkl",
    "name": "MCP · Acme Research",
    "preview": "pk-…9fQ2",
    "budget": { "limit": 5, "used": 0.42, "currency": "USD" }
  }
}

用 userId 作为稳定标识,把 Pikeway 账户关联到你的用户。根据用户的注册方式,email 或 walletAddress 可能为 null。

可用余额
curl https://gw.pikeway.ai/v1/wallet/balance -H "Authorization: Bearer $ACCESS_TOKEN"
# → { "balance": { "value": 18.3, … }, "keyBudget": { "limit": 5, "used": 0.42, "remaining": 4.58, … },
#     "spendable": { "value": 4.58, "currency": "USD" } }

spendable 取用户余额和你剩余授权额度中较小的一个。然后就可以调用任意端点:

调用端点
curl -X POST https://gw.pikeway.ai/v1/run \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"provider":"birdeye","endpoint":"/defi/price","input":{"address":"So11111111111111111111111111111111111111112"}}'
7

在 token 过期前刷新

刷新会同时轮换两个 token:你会拿到新的 access token 和新的 refresh token;旧 access token 立即失效,旧 refresh token 不能再用。上限和已花金额都会延续,刷新不会重置用户的预算。

Body
grant_typestring必填
refresh_token
refresh_tokenstring必填
你保存的最新 refresh token。
client_idstring
建议发送;发送时必须一致。
bash
curl -X POST https://gw.pikeway.ai/api/mcp-oauth/token \
  -d grant_type=refresh_token \
  -d refresh_token=pkr-… \
  -d client_id=mcp_Xr4k9pQ2vL8sT1wZb7nYdA3e
同一个用户的刷新要串行执行。如果两个 worker 同时用同一个 refresh token 刷新,只有一个会成功,另一个会收到 invalid_grant。拿到新 token 后先保存再使用。
8

处理吊销和额度

用户可以随时在 控制台 → Keys 吊销你的应用;余额或授权额度用完时,调用也会停止。请把以下响应转换成清晰的界面提示:

位置响应含义与处理
API 调用401 invalid or revoked API keyaccess token 已过期或被用户吊销。先尝试刷新;刷新失败就请用户重新连接。
API 调用402 api key spend limit reached你的应用用完了用户授予的全部额度。请用户重新连接并选择更高的上限。
API 调用402 insufficient balance用户的 Pikeway 余额不足。引导他们到 /console/billing 充值。
令牌端点400 invalid_grantcode 过期或被重复使用、verifier 或 redirect_uri 不匹配,或 refresh token 已被吊销或用过。重新发起登录流程。
令牌端点400 invalid_request缺少 code 或 code_verifier。
令牌端点400 unsupported_grant_typegrant_type 只能是 authorization_code 或 refresh_token。

令牌端点的错误使用标准 OAuth 格式:{"error":"invalid_grant","error_description":"…"}。

安全须知

access token 是一把会花用户钱的真实 key。两个 token 都要保存在服务端、加密存储,不要写进日志,也不要发给浏览器。
  • 始终发送并校验 state,每次登录都生成新的 PKCE verifier。
  • 授权码只能用一次。如果同一个 code 被提交两次,Pikeway 会视为被盗用,并吊销用它签发的 token。
  • 只注册你能控制的重定向地址,并保持列表精简。重定向地址按完全一致匹配。
  • 没有 client secret,所以 client_id 不是敏感信息。安全性来自 PKCE 和重定向地址的完全匹配。
  • 要从你这边断开连接,删除保存的 token 即可;access token 最多 30 天后过期。要立即失效,需要用户在 控制台 → Keys 删除这把 key。