Api.Airforce
OAUTH 提供方

使用 Airforce 登录

让你的用户授权你的应用访问他们的 Api.Airforce 账户。带 PKCE 的标准 OAuth 2.0 Authorization Code 流程。

适用对象

你正在构建一个应用(playground、代理、移动客户端、…),希望你的用户接入他们的 Airforce 账户,以便通过你的 UI 运行聊天或图像生成,而不必把原始 API 密钥分享给你。使用此流程。

你会得到一个不透明的 access_token (24h TTL),其作用域限定为你的应用请求且用户批准的范围。将其作为 Bearer 头用于 /v1/* 端点或 /oauth/userinfo.

1. 获取 client_id + client_secret

Phase 1 是管理员管理的注册。请联系我们并提供:

  • 应用名称(在同意屏幕上展示给你的用户)
  • 一句话描述
  • 主页 URL(可选,显示在同意屏幕)
  • 方形 logo URL(可选)
  • 一个或多个精确的 redirect_uri(仅 https://,除开发用 http://localhost)
  • 你需要哪些 scope(见下文)

我们将回传给你 client_id 和一个一次性的 client_secret. 把 secret 保存在服务端 — 如果你是纯 SPA / 原生应用且没有后端,可以跳过 secret,只依赖 PKCE。

2. Scope

Scope授予的权限
profile通过 /oauth/userinfo 读取 user 对象(id、username、plan、已验证时的关联邮箱)。
chatPOST /v1/chat/completions, /v1/messages, /v1/messages/count_tokens, /v1/responses.
imagesPOST /v1/images/generations.
keys:read保留 — 列出用户的 Airforce API 密钥(Phase 2)。
keys:write (敏感)保留 — 创建 + 撤销用户的 Airforce API 密钥(Phase 2)。敏感 scope。

多个 scope 在 scope 查询参数中以空格分隔: scope=profile chat images.

3. 流程

3.1 生成 PKCE 对

在客户端,重定向到 /oauth/authorize 之前,生成一个随机 verifier 和匹配的 SHA-256 challenge。

// In your app, before redirecting to /oauth/authorize:
const verifier = randomString(64); // 43..128 chars [A-Z][a-z][0-9]-._~
const challenge = base64UrlNoPad(sha256(verifier));
sessionStorage.setItem('airforce_pkce_verifier', verifier);

3.2 重定向到 /oauth/authorize

构造 authorize URL 并把用户送过去。他会看到我们的同意屏幕,做出决定,然后被重定向回你这里。

https://api.airforce/oauth/authorize?
  response_type=code
  &client_id=airforce_xxxxxxxxxxxxxxxxxxxxxxxxx
  &redirect_uri=https://your.app/oauth/callback
  &scope=profile chat
  &state=<random opaque>
  &code_challenge=<base64url(sha256(verifier))>
  &code_challenge_method=S256

用户到达我们的同意屏幕,登录(如果尚未登录),然后批准或拒绝。我们会重定向回你的 redirect_uri 并附上短期的 ?code=… (批准时), ?error=access_denied (拒绝时)。你原始的 state 会被回传 — 请验证是否匹配。

3.3 用 code 换取 access_token

从你的后端,用 code(加上 PKCE verifier)换取一个 access token。

curl -X POST https://api.airforce/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  --data-urlencode "grant_type=authorization_code" \
  --data-urlencode "code=$CODE" \
  --data-urlencode "redirect_uri=https://your.app/oauth/callback" \
  --data-urlencode "code_verifier=$VERIFIER"

响应(24h TTL):

{
  "access_token": "airf_oat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "token_type": "Bearer",
  "expires_in": 86400,
  "scope": "profile chat"
}

3.4 使用 token

调用 userinfo 端点或所授予 scope 允许的任何 /v1/* 路由:

# Profile lookup
curl https://api.airforce/oauth/userinfo \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# Chat (requires scope=chat)
curl https://api.airforce/v1/chat/completions \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"model":"gpt-4o-mini","messages":[{"role":"user","content":"Hi"}]}'

/oauth/userinfo 响应

{
  "id": "user-uuid",
  "username": "foo",
  "plan": "free",
  "is_admin": false,
  "email": "[email protected]",
  "email_verified": true,
  "github_email": "[email protected]",
  "discord_username": "foo#1234"
}

诸如 email, github_email, discord_username 之类的字段,只有当用户确实已验证 / 关联时才会出现。请同时考虑存在与不存在的情况。

撤销 token

当用户从你的应用登出时,撤销 token 以避免它在后台继续扣费:

curl -X POST https://api.airforce/oauth/revoke \
  --data-urlencode "token=$ACCESS_TOKEN"

RFC 7009。无论 token 是否存在,始终返回 200 (无 oracle)。

安全注意事项

  • PKCE 对公共客户端是强制的 (没有服务端 client_secret)。我们仅接受 S256 — code_challenge_method=plain 会被拒绝。
  • redirect_uri 为精确匹配。 没有前缀 / 通配符匹配。如果你需要多个环境,请为每个环境注册一个 URI。
  • Token 拥有 24h TTL 且暂时没有 refresh token — 过期时让用户重新走一遍 /oauth/authorize 。对于长期运行的代理,启动时提示并把 token 存到安全存储。
  • 不要把 client_secret 存放在客户端代码中。 如果你的应用是纯浏览器 SPA 或原生客户端,请在无服务器情况下注册并依赖 PKCE。
  • 用户可随时从他们的 dashboard → Apps 标签撤销你的应用。通过重新运行 OAuth 流程来处理 401。
  • Phase 1 覆盖范围: OAuth bearer token 适用于 /v1/chat/completions, /v1/messages, /v1/messages/count_tokens, /v1/responses, /v1/images/generations, 和 /oauth/userinfo. 音频、视频、语音和 character 端点在 Phase 1 仍需要常规的 Airforce API 密钥。

注册

发送邮件至 [email protected] 或在 Discord 上联系我们,并附上上面列出的注册详情。我们将在数小时内把你的凭证发回。

设置卡住,或想要免费密钥?来我们的 Discord 问问社区吧。

加入我们的 Discord