Connexion avec Airforce
Permets à tes utilisateurs d'autoriser ton application à accéder à leur compte Api.Airforce. Flux standard OAuth 2.0 Authorization Code avec PKCE.
À qui c'est destiné
Tu construis une application (playground, agent, client mobile, …) et tu veux que tes utilisateurs branchent leur compte Airforce pour qu'ils puissent lancer du chat ou de la génération d'images via ton interface sans te confier leur clé API brute. Utilise ce flux.
Tu obtiendras un access_token opaque (24h TTL) limité à ce que ton app a demandé et que l'utilisateur a approuvé. Utilise-le comme en-tête Bearer sur les endpoints /v1/* ou /oauth/userinfo.
1. Obtenir un client_id + client_secret
La Phase 1 est une inscription gérée par l'administrateur. Contacte-nous avec :
- Nom de l'app (affiché sur l'écran de consentement de tes utilisateurs)
- Description en une phrase
- URL du site (optionnel, affichée sur le consentement)
- URL du logo carré (optionnel)
- Une ou plusieurs redirect_uri exactes (uniquement https://, sauf http://localhost pour le dev)
- Quels scopes tu as besoin (voir ci-dessous)
On te renvoie client_id et un client_secret. Stocke le secret côté serveur — si tu es une pure SPA / app native sans backend, tu peux ignorer le secret et te baser uniquement sur PKCE.
2. Scopes
| Scope | Ce qu'il accorde |
|---|---|
| profile | Lit l'objet user via /oauth/userinfo (id, username, plan, emails liés s'ils sont vérifiés). |
| chat | POST /v1/chat/completions, /v1/messages, /v1/messages/count_tokens, /v1/responses. |
| images | POST /v1/images/generations. |
| keys:read | Réservé — liste les clés API Airforce de l'utilisateur (Phase 2). |
| keys:write (SENSIBLE) | Réservé — crée + révoque les clés API Airforce de l'utilisateur (Phase 2). Scope sensible. |
Plusieurs scopes sont séparés par des espaces dans le paramètre de requête scope : scope=profile chat images.
3. Le flux
3.1 Générer la paire PKCE
Dans ton client, avant de rediriger vers /oauth/authorize, génère un verifier aléatoire et le challenge SHA-256 correspondant.
// 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 Rediriger vers /oauth/authorize
Construis l'URL d'autorisation et envoie l'utilisateur. Il verra notre écran de consentement, décidera, et sera redirigé vers toi.
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=S256L'utilisateur arrive sur notre écran de consentement, se connecte (si ce n'est pas déjà fait), et approuve ou refuse. On redirige vers ta redirect_uri avec un ?code=… à courte durée de vie en cas d'approbation, ?error=access_denied en cas de refus. Ton state d'origine est renvoyé — vérifie qu'il correspond.
3.3 Échanger le code contre access_token
Depuis ton backend, échange le code (plus le verifier PKCE) contre un 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"Réponse (24h TTL) :
{
"access_token": "airf_oat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"token_type": "Bearer",
"expires_in": 86400,
"scope": "profile chat"
}3.4 Utiliser le token
Appelle l'endpoint userinfo ou n'importe quelle route /v1/* autorisée par les scopes accordés :
# 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"}]}'Réponse de /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"
}Des champs comme email, github_email, discord_username n'apparaissent que lorsque l'utilisateur les a effectivement vérifiés / liés. Prévois leur présence comme leur absence.
Révoquer un token
Quand un utilisateur se déconnecte de ton app, révoque le token pour qu'il ne continue pas à facturer son compte en arrière-plan :
curl -X POST https://api.airforce/oauth/revoke \
--data-urlencode "token=$ACCESS_TOKEN"RFC 7009. Renvoie toujours 200 que le token ait existé ou non (pas d'oracle).
Notes de sécurité
- PKCE est obligatoire pour les clients publics (pas de client_secret côté serveur). On n'accepte que S256 —
code_challenge_method=plainest rejeté. - redirect_uri est en correspondance exacte. Pas de correspondance par préfixe / wildcard. Si tu as besoin de plusieurs environnements, enregistre une URI par environnement.
- Les tokens ont une TTL de 24h et pas encore de refresh tokens — à expiration, fais repasser l'utilisateur par
/oauth/authorizeà nouveau. Pour les agents longue durée, demande au démarrage et stocke le token dans un stockage sécurisé. - Ne stocke pas client_secret dans du code client. Si ton app est une SPA navigateur uniquement ou un client natif, enregistre-toi sans serveur et appuie-toi sur PKCE.
- Les utilisateurs peuvent révoquer ton app à tout moment depuis leur dashboard → onglet Apps. Gère le 401 en relançant le flux OAuth.
- Couverture Phase 1 : Les bearer tokens OAuth fonctionnent sur
/v1/chat/completions,/v1/messages,/v1/messages/count_tokens,/v1/responses,/v1/images/generations, et/oauth/userinfo. Les endpoints audio, vidéo, voix et character nécessitent toujours une clé API Airforce normale en Phase 1.
S'inscrire
Email à [email protected] ou contacte-nous sur Discord avec les détails d'inscription listés ci-dessus. Tu recevras tes identifiants en quelques heures.
Bloqué lors de la configuration ou besoin d'une clé gratuite ? Demandez à la communauté sur notre Discord.
Rejoignez notre Discord