Войти через Airforce
Позволь своим пользователям авторизовать твоё приложение для доступа к их аккаунту Api.Airforce. Стандартный OAuth 2.0 Authorization Code flow с PKCE.
Для кого это
Ты строишь приложение (playground, агент, мобильный клиент, …) и хочешь, чтобы твои пользователи подключили свой аккаунт Airforce, чтобы они могли запускать чат или генерацию изображений через твой интерфейс, не делясь с тобой сырым API-ключом. Используй этот flow.
Ты получишь непрозрачный access_token (24h TTL), ограниченный тем, что запросило твоё приложение и одобрил пользователь. Используй его как Bearer-заголовок к /v1/* -эндпоинтам или /oauth/userinfo.
1. Получить client_id + client_secret
Phase 1 — это регистрация, управляемая админом. Напиши нам с:
- Название приложения (показывается пользователям на экране согласия)
- Описание одним предложением
- URL домашней страницы (опционально, показывается на согласии)
- URL квадратного логотипа (опционально)
- Один или несколько точных redirect_uri (только https://, кроме http://localhost для dev)
- Какие scope нужны (см. ниже)
Мы пришлём тебе обратно client_id и одноразовый client_secret. Храни secret на стороне сервера — если ты чистая SPA / нативное приложение без бэкенда, можешь пропустить secret и полагаться только на PKCE.
2. Scope'ы
| Scope | Что он даёт |
|---|---|
| profile | Читает объект user через /oauth/userinfo (id, username, plan, привязанные email при их верификации). |
| chat | POST /v1/chat/completions, /v1/messages, /v1/messages/count_tokens, /v1/responses. |
| images | POST /v1/images/generations. |
| keys:read | Зарезервировано — выводит API-ключи Airforce пользователя (Phase 2). |
| keys:write (ЧУВСТВИТЕЛЬНЫЙ) | Зарезервировано — создаёт + отзывает API-ключи Airforce пользователя (Phase 2). Чувствительный scope. |
Несколько scope разделяются пробелами в параметре запроса scope : scope=profile chat images.
3. Flow
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
Построй 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 Использовать токен
Вызови эндпоинт userinfo или любой маршрут /v1/*, разрешённый предоставленными scope:
# 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 появляются только когда пользователь действительно их верифицировал / привязал. Планируй на присутствие и отсутствие.
Отзыв токена
Когда пользователь выходит из твоего приложения, отзови токен, чтобы он не продолжал тарифицировать его аккаунт в фоне:
curl -X POST https://api.airforce/oauth/revoke \
--data-urlencode "token=$ACCESS_TOKEN"RFC 7009. Всегда возвращает 200 независимо от того, существовал ли токен (без oracle).
Заметки по безопасности
- PKCE обязателен для публичных клиентов (без серверного client_secret). Принимаем только S256 —
code_challenge_method=plainотклоняется. - redirect_uri — точное совпадение. Никакого префикс / wildcard сопоставления. Если нужны разные окружения, зарегистрируй по одному URI на окружение.
- У токенов 24h TTL и refresh-токенов пока нет — при истечении прогоняй пользователя через
/oauth/authorizeещё раз. Для долгоживущих агентов спрашивай при старте и храни токен в защищённом хранилище. - Не храни client_secret в клиентском коде. Если твоё приложение — чисто браузерная SPA или нативный клиент, регистрируйся без сервера и полагайся на PKCE.
- Пользователи могут отозвать твоё приложение в любой момент из dashboard → вкладка Apps. Обрабатывай 401, перезапуская OAuth-flow.
- Покрытие Phase 1: OAuth bearer-токены работают на
/v1/chat/completions,/v1/messages,/v1/messages/count_tokens,/v1/responses,/v1/images/generations, и/oauth/userinfo. Эндпоинты audio, video, voice и character в Phase 1 всё ещё требуют обычного API-ключа Airforce.
Зарегистрироваться
Email на [email protected] или напиши нам на Discord с регистрационными данными, перечисленными выше. Мы пришлём тебе credentials в течение нескольких часов.
Не получается настроить или нужен бесплатный ключ? Спросите сообщество в нашем Discord.
Присоединяйтесь к нашему Discord