OAuth برای CLI

فلوی PKCE که AiraCode CLI برای ورود استفاده می‌کنه — و چطور توی ابزار خودت سوارش کنی.

AiraCode از OAuth 2.0 + PKCE استفاده می‌کنه — همون استانداردی که Anthropic، OpenAI، GitHub و … برای CLIها به‌کار می‌برن. تفاوت اینه که provider اینجا airachat.ir‌ست، نه console.anthropic.com. یعنی توسعه‌دهنده نه به VPN نیاز داره، نه به کارت بین‌المللی.

فلوی کامل

  1. CLI یک listener loopback روی http://localhost:<PORT>/callback راه می‌اندازه.
  2. یک code_verifier تصادفی می‌سازه و SHA-256‌اش رو به‌عنوان code_challenge توی URL authorize قرار می‌ده.
  3. مرورگر باز می‌شه روی https://app.airachat.ir/api/auth/oauth/authorize با پارامترهای استاندارد PKCE.
  4. سرور یه صفحهٔ RTL فارسی نشون می‌ده: ورودی شمارهٔ موبایل → SMS OTP → تایید کد.
  5. پس از تایید، یک code با TTL ۱۲۰ ثانیه ساخته و مرورگر را به redirect_uri?code=…&state=… هدایت می‌کنه.
  6. Listener loopback کد رو می‌گیره و POST /auth/oauth/token با code + code_verifier می‌زنه.
  7. سرور PKCE رو verify می‌کنه، access_token (JWT) و refresh_token برمی‌گردونه.
  8. Token توی Keychain (macOS) یا libsecret (Linux) یا DPAPI (Windows) ذخیره می‌شه.

Endpoint‌ها

GET /auth/oauth/authorize

پارامترهای الزامی:

  • client_id=airacode-cli (تنها client رجیستر شده در نسخهٔ ۰.۱)
  • response_type=code
  • redirect_uri=http://localhost:<PORT>/callback (loopback فقط)
  • code_challenge=<base64url(sha256(code_verifier))>
  • code_challenge_method=S256
  • state=<random>
  • scope=user:inference user:profile

پاسخ: HTML page (فارسی، RTL) برای وارد کردن شمارهٔ موبایل.

POST /auth/oauth/token

برای exchange کد:

POST /auth/oauth/token
Content-Type: application/json

{
  "grant_type": "authorization_code",
  "code": "<code from redirect>",
  "code_verifier": "<original PKCE verifier>",
  "redirect_uri": "http://localhost:9876/callback",
  "client_id": "airacode-cli"
}

→ 200 OK
{
  "access_token": "eyJ...",
  "refresh_token": "eyJ...",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "user:inference user:profile user:sessions:airacode",
  "account": {
    "uuid": "<user-uuid>",
    "email_address": "+989121234567"
  },
  "organization": {
    "uuid": "<user-uuid>"
  }
}

برای رفرش (هر زمان token در شرف انقضاست):

POST /auth/oauth/token
{
  "grant_type": "refresh_token",
  "refresh_token": "<previous refresh>",
  "client_id": "airacode-cli"
}

GET /auth/oauth/profile

userinfo. نیاز به Bearer.

curl -H "Authorization: Bearer $TOKEN" \
     https://app.airachat.ir/api/auth/oauth/profile

→ {
  "account": {
    "uuid": "...",
    "email": "+989121234567",
    "display_name": "...",
    "created_at": "..."
  },
  "organization": {
    "uuid": "...",
    "organization_type": "claude_pro",
    "rate_limit_tier": "pro",
    ...
  }
}

POST /auth/oauth/revoke

برای logout — refresh token رو invalid می‌کنه.

curl -X POST \
     -d "token=<refresh-token>" \
     https://app.airachat.ir/api/auth/oauth/revoke

برای ابزار خودت

می‌خوای ابزارت هم با OAuth آیراچت لاگین کنه (مثل اینکه AiraCode می‌کنه)؟ فعلاً فقط airacode-cli به‌عنوان client ثبت شده. اگه می‌خوای client جدید اضافه کنی، به info@airachat.ir ایمیل بزن.