Skip to content
GuidesJuly 19, 2026

Sign in with AnyRouter: để người dùng mang tài khoản LLM của họ

Nếu app cần LLM API để chạy, bạn có hai lựa chọn tệ: tự ship key rồi gánh hóa đơn inference của mọi user, hoặc bắt từng người dán key nhà cung cấp thô. "Sign in with AnyRouter" là lựa chọn thứ ba — họ đăng nhập bằng tài khoản AnyRouter, số dư của họ nuôi inference. Bạn nhận key tạm, chỉ inference, theo từng user, và không đụng billing model.

Vì sao app không nên sở hữu hóa đơn inference

Gần như mọi app đang dựng đều muốn LLM ở đâu đó: hộp chat, nút tóm tắt, agent làm việc. Nhưng vừa thêm là bạn thừa kế bài toán billing. Nếu ship key nhà cung cấp của mình, mọi request user gửi nằm trên hóa đơn bạn — một user hăng có thể chạy bill lớn hơn số họ trả bạn, và bạn thành người đo, rate-limit, và canh gian lận inference mà bạn chẳng muốn chạy.

Lối thoát thường gặp là bắt từng user dán key OpenAI hoặc Anthropic thô. Chạy được, nhưng trải nghiệm tệ: họ quản secret không hiểu, bạn lưu credential sống lâu làm được nhiều hơn gọi model, và một lỗi log là lộ. Không lựa chọn nào là thứ bạn muốn: để user trả inference của họ, và đừng đụng key của họ.

Đó đúng là thứ "Sign in with AnyRouter" cho bạn. AnyRouter là nền app dựng quanh — gateway đã có tài khoản user, credit hoặc free tier, và mọi model trong một catalog. Thêm nút đăng nhập, user duyệt một lần, app nhận key tạm, chỉ inference, scoped đúng user đó. Mọi request tính vào tài khoản họ, không phải bạn. Bạn ship sản phẩm; AnyRouter lo billing model, failover nhà cung cấp, và audit log.

Luồng chạy thế nào

Đây là OAuth 2.1 authorization-code chuẩn với PKCE. App của bạn là public client — không có client secret phải giữ, nên chạy được từ frontend chỉ trình duyệt. User được đẩy tới màn consent AnyRouter, duyệt scope chỉ inference, callback đổi code lấy key sk-ar-v1-* sống ngắn.

sequenceDiagram
  participant App as Your app
  participant AR as AnyRouter
  participant User

  App->>AR: (once) POST /oauth/register {app_type:"signin"}
  AR-->>App: client_id (public, safe to embed)
  User->>App: clicks "Sign in with AnyRouter"
  App->>AR: GET /oauth/authorize?client_id&redirect_uri&code_challenge
  AR->>User: consent screen — your app name + inference scope
  User->>AR: Approve
  AR-->>App: redirect_uri?code=...
  App->>AR: POST /oauth/token {code, code_verifier}
  AR-->>App: access_token = sk-ar-v1-* (expires in 30d)
  App->>AR: POST /chat/completions (Bearer sk-ar-v1-*)
  Note over AR: billed to the user's account
Đăng ký một lần, rồi mỗi user đăng nhập để mint key tính vào tài khoản họ.

Mọi endpoint dưới đây nằm dưới https://anyrouter.dev/api/v1/mcp/oauth/* — cùng gateway OAuth thống nhất AnyRouter dùng cho MCP và managed access enterprise. Đăng ký một lần, rồi chạy cặp authorize/token mỗi user.

Bước 1 — Đăng ký app một lần

Đăng ký mở: không cần tài khoản AnyRouter để đăng ký app, không client secret. Gửi tên app, redirect URI chính xác (chỉ https, localhost được lúc dev), và app_type: "signin".

curl https://anyrouter.dev/api/v1/mcp/oauth/register \
  -H "Content-Type: application/json" \
  -d '{
    "client_name": "My AI App",
    "redirect_uris": ["https://myapp.example/callback"],
    "app_type": "signin",
    "origin_url": "https://myapp.example"
  }'
POST /api/v1/mcp/oauth/register — trả về client_id công khai.

Response chứa client_id. Nó công khai — nhúng vào frontend không lo. App signin vào flagged cho review admin nhẹ và hiện trong admin console AnyRouter; đó là cách app lạm dụng bị suspend, và không chặn user đăng nhập.

Bước 3 — Đổi code lấy key

Trên trang callback, kiểm state khớp thứ bạn lưu, rồi POST code và PKCE verifier tới token endpoint. Nó nhận cả form-encoded và JSON.

const params = new URLSearchParams(location.search)
if (params.get("state") !== sessionStorage.getItem("ar_state")) {
  throw new Error("State mismatch — restart sign-in")
}

const res = await fetch("https://anyrouter.dev/api/v1/mcp/oauth/token", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    grant_type: "authorization_code",
    code: params.get("code"),
    redirect_uri: "https://myapp.example/callback",
    client_id: "your_client_id",
    code_verifier: sessionStorage.getItem("ar_verifier"),
  }),
})

const token = await res.json()
// {
//   "access_token": "sk-ar-v1-...",
//   "token_type": "Bearer",
//   "scope": "inference read:profile",
//   "expires_in": 2592000
// }
saveTokenForThisUser(token.access_token)
POST /api/v1/mcp/oauth/token — trả key inference của user.

Lưu một token mỗi user. Giá trị sk-ar-v1-* đó là key AnyRouter thường từ góc app — nhưng chỉ chạy inference, scoped đúng user này, và hết hạn (mặc định 30 ngày).

Bước 4 — Chạy inference như user

Dùng token đúng như mọi API key AnyRouter. Mọi request đo theo số dư user đã đăng nhập — credit của họ, hoặc free tier nếu họ đang ở đó. Bạn không thấy hóa đơn model.

const res = await fetch("https://anyrouter.dev/api/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "google/gemini-3.5-flash",
    messages: [{ role: "user", content: "Hello from my app!" }],
  }),
})
POST /api/v1/chat/completions — tính vào user đã đăng nhập.

Vì đây là key AnyRouter thật, bạn nhận cả gateway miễn phí: mọi model trong catalog theo id, failover tự động khi nhà cung cấp bị rate-limit, và dialect OpenAI, Anthropic, Responses cùng một endpoint. Để hiện badge "Signed in as …", scope read:profile cho gọi GET /api/v1/me lấy display name, avatar, và gói.

User thấy và kiểm soát gì

Màn consent cố ý hẹp. Token sign-in mang đúng hai scope, không gì khác — xin thêm không có hiệu lực, AnyRouter kẹp lại hai cái này:

ScopeCho phép gì
inferenceGọi /chat/completions, /messages, /responses, /embeddings — tính vào user
read:profileGET /api/v1/me — display name, avatar, gói

Phần quan trọng là token sign-in **không** làm được gì: không tạo hay thu hồi API key, không đọc usage hay billing, không đổi setting tài khoản, không thừa quyền admin. Không có quyền quản trị nào — tệ nhất token bị lộ chỉ tiêu một ngân sách inference có trần của chính user trước khi hết hạn.

User vẫn kiểm soát phía kia. Từ **Dashboard → Connected apps** họ thu hồi app bất cứ lúc nào, vô hiệu mọi token bạn đã nhận cho user đó. Cả hết hạn và thu hồi hiện cùng cách với code bạn — 401. Không refresh token ở v1: coi mọi 401 là "đăng nhập lại" và chạy lại luồng authorize im lặng. Nếu user vẫn đăng nhập AnyRouter, họ đi qua consent rồi về với token mới trong vài giây.

Dựng trên nền, không vòng quanh nó

Điểm chính: inference thôi là bài của bạn. Bạn không cấp key, không ứng hóa đơn model, không lưu secret nhà cung cấp của ai, không dựng hệ đo. User mang tài khoản họ đã có; AnyRouter lo tiền và model. App chỉ gọi endpoint.

Tham chiếu endpoint đầy đủ, scope, và snippet trình duyệt từ đầu đến cuối.

Đọc hướng dẫn Sign in with AnyRouter

Gửi request đầu trong hai phút

Bắt đầu miễn phí với key của bạn, hoặc nạp rồi trả theo token. Go: $4 credit/tháng — $2/tháng, hoặc miễn phí khi góp một provider key.

Bắt đầu miễn phí