Api.Airforce
NHÀ CUNG CẤP OAUTH

Đăng nhập bằng Airforce

Cho phép người dùng của bạn ủy quyền cho ứng dụng của bạn truy cập tài khoản Api.Airforce của họ. Luồng chuẩn OAuth 2.0 Authorization Code với PKCE.

Dành cho ai

Bạn đang xây dựng một ứng dụng (playground, agent, mobile client, …) và muốn người dùng kết nối tài khoản Airforce của họ để họ có thể chạy chat hoặc tạo hình ảnh qua giao diện của bạn mà không phải chia sẻ API key thô với bạn. Hãy dùng luồng này.

Bạn sẽ nhận được một access_token opaque (24h TTL) giới hạn theo những gì ứng dụng của bạn yêu cầu và người dùng đã phê duyệt. Dùng nó làm header Bearer đối với các endpoint /v1/* hoặc /oauth/userinfo.

1. Lấy client_id + client_secret

Phase 1 là đăng ký do admin quản lý. Hãy liên hệ chúng tôi với:

  • Tên ứng dụng (hiển thị trên màn hình đồng ý cho người dùng của bạn)
  • Mô tả một câu
  • URL trang chủ (tùy chọn, hiển thị trên màn hình đồng ý)
  • URL logo vuông (tùy chọn)
  • Một hoặc nhiều redirect_uri chính xác (chỉ https://, ngoại trừ http://localhost cho dev)
  • Scope nào bạn cần (xem bên dưới)

Chúng tôi gửi lại cho bạn client_id và một client_secret. Lưu secret ở phía server — nếu bạn là một SPA thuần túy / ứng dụng native không có backend, bạn có thể bỏ qua secret và chỉ dựa vào PKCE.

2. Scope

ScopeCấp cái gì
profileĐọc đối tượng user qua /oauth/userinfo (id, username, plan, email được liên kết khi đã xác minh).
chatPOST /v1/chat/completions, /v1/messages, /v1/messages/count_tokens, /v1/responses.
imagesPOST /v1/images/generations.
keys:readDành riêng — liệt kê các API key Airforce của người dùng (Phase 2).
keys:write (NHẠY CẢM)Dành riêng — tạo + thu hồi các API key Airforce của người dùng (Phase 2). Scope nhạy cảm.

Nhiều scope được phân tách bằng dấu cách trong tham số truy vấn scope : scope=profile chat images.

3. Luồng

3.1 Tạo cặp PKCE

Trong client, trước khi chuyển hướng đến /oauth/authorize, tạo một verifier ngẫu nhiên và challenge SHA-256 tương ứng.

// 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 Chuyển hướng đến /oauth/authorize

Xây URL authorize và gửi người dùng đến đó. Họ sẽ thấy màn hình đồng ý của chúng tôi, quyết định, và được chuyển hướng lại cho bạn.

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

Người dùng đến màn hình đồng ý của chúng tôi, đăng nhập (nếu chưa), rồi phê duyệt hoặc từ chối. Chúng tôi chuyển hướng lại đến redirect_uri của bạn với một ?code=… ngắn hạn khi phê duyệt, ?error=access_denied khi từ chối. Tham số state ban đầu của bạn được trả về — hãy xác minh nó khớp.

3.3 Đổi code lấy access_token

Từ backend của bạn, đổi code (cộng với PKCE verifier) lấy một 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"

Phản hồi (24h TTL):

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

3.4 Sử dụng token

Gọi endpoint userinfo hoặc bất kỳ route /v1/* nào mà các scope được cấp cho phép:

# 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"}]}'

Phản hồi /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"
}

Các trường như email, github_email, discord_username chỉ xuất hiện khi người dùng thực sự đã xác minh / liên kết chúng. Hãy lập kế hoạch cho cả sự hiện diện và vắng mặt.

Thu hồi một token

Khi người dùng đăng xuất khỏi ứng dụng của bạn, hãy thu hồi token để nó không tiếp tục tính phí tài khoản của họ ở chế độ nền:

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

RFC 7009. Luôn trả về 200 bất kể token có tồn tại hay không (không có oracle).

Lưu ý bảo mật

  • PKCE là bắt buộc đối với client công khai (không có client_secret phía server). Chúng tôi chỉ chấp nhận S256 — code_challenge_method=plain bị từ chối.
  • redirect_uri là khớp chính xác. Không có khớp tiền tố / wildcard. Nếu bạn cần nhiều môi trường, hãy đăng ký một URI cho mỗi môi trường.
  • Token có TTL 24h và chưa có refresh token — khi hết hạn, hãy đưa người dùng đi qua /oauth/authorize lại. Đối với các agent chạy lâu dài, hãy hỏi khi khởi động và cất giữ token trong lưu trữ an toàn.
  • Không lưu client_secret trong code phía client. Nếu ứng dụng của bạn là SPA chỉ chạy trên trình duyệt hoặc client native, hãy đăng ký mà không cần server và dựa vào PKCE.
  • Người dùng có thể thu hồi ứng dụng của bạn bất kỳ lúc nào từ dashboard → tab Apps. Xử lý 401 bằng cách chạy lại luồng OAuth.
  • Phạm vi Phase 1: Token bearer OAuth hoạt động trên /v1/chat/completions, /v1/messages, /v1/messages/count_tokens, /v1/responses, /v1/images/generations, và /oauth/userinfo. Các endpoint audio, video, voice và character vẫn yêu cầu một API key Airforce thông thường trong Phase 1.

Đăng ký

Email đến [email protected] hoặc liên hệ chúng tôi trên Discord với chi tiết đăng ký được liệt kê ở trên. Chúng tôi sẽ gửi lại thông tin xác thực trong vài giờ.

Gặp khó khi thiết lập hoặc muốn key miễn phí? Hỏi cộng đồng trên Discord của chúng tôi.

Tham gia Discord của chúng tôi