Créer une transaction de connexion
POST /fapi/v1/transactions · appelé depuis l'hôte de connexion de l'environnement
Démarre une transaction de connexion pour une application. La page de connexion hébergée, les composants d'interface et les clients
headless appellent cet point de terminaison sur l'hôte de connexion de l'environnement (un sous-domaine keenauth.app ou un domaine
personnalisé vérifié). La réponse définit le cookie de transaction __Host-idp_ltx (Secure, HttpOnly, SameSite=Lax, valable 15 minutes) ;
les étapes suivantes utilisent ce cookie.
Requête
En-têtes :
| En-tête | Obligatoire | Description |
|---|---|---|
Idp-Client |
oui | Identifiant du SDK, <package>/<version> (<runtime>/<version>). |
Origin |
oui | Doit être exactement https://<hôte de connexion>. |
Corps :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
client_id |
string | oui | L'identifiant client de l'application. |
redirect_uri |
string (URI) | oui | L'une des URI de redirection enregistrées de l'application. |
Réponse
201 Created avec l'objet de transaction :
{
"schema_version": 1,
"state": "identifier_pending",
"next_steps": [{ "step": "identifier", "fields": ["identifier"] }],
"csrf_token": "<token>",
"expires_at": "2026-10-05T10:15:00Z"
}
Renvoyez csrf_token dans l'en-tête Idp-Csrf-Token à chaque requête de cette transaction qui modifie un état.
Lorsque la demande d'autorisation désigne une organisation qui exige une authentification unique, la réponse peut déjà être
federated_redirect avec redirect_url (une seule connexion : naviguez alors vers cette URL dans la fenêtre de premier niveau) ou contenir
sso_connections (plusieurs : envoyez le choix avec l'étape sso_start).
Transactions sans interface liées à DPoP
Une application SPA ou native de première partie, sur sa propre origine, démarre une connexion sans interface avec un en-tête DPoP (RFC 9449) : une preuve
signée avec une clé que le client conserve (clé WebCrypto non extractible dans un navigateur, magasin de clés de la plateforme sur un appareil),
avec htm POST et htu https://<hôte de connexion>/fapi/v1/transactions. La transaction est alors liée à cette clé
au lieu d'un cookie : aucun cookie n'est défini et l'objet ne contient pas de csrf_token. Chaque requête suivante de la transaction envoie
une nouvelle preuve issue de la même clé.
Champs supplémentaires du corps, vérifiés selon les règles du point de terminaison d'autorisation :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
code_challenge |
string | oui | Challenge PKCE S256 (RFC 7636). |
code_challenge_method |
string | oui | S256. |
scope |
string | non | Scopes séparés par des espaces, par exemple openid profile email offline_access. |
state |
string | non | Renvoyé avec le code d'autorisation. |
nonce |
string | non | Le nonce du jeton ID. |
organization |
string | non | Identifiant ou nom de l'organisation. |
ui_locales |
string | non | Langues préférées. |
resource |
string (URI) | non | Indicateur de ressource (RFC 8707). |
Origin peut être l'hôte de connexion ou l'une des origines web autorisées de l'application ; une application native n'en envoie aucune. Seules les
applications de première partie peuvent en démarrer une. Un champ que le point de terminaison d'autorisation refuse renvoie 422 validation_failed avec
le code d'erreur OAuth dans errors[].code. Lorsque le serveur répond 401 use_dpop_nonce, signez une nouvelle preuve avec la valeur
de l'en-tête de réponse DPoP-Nonce et réessayez. Envoyer ces champs sans en-tête DPoP renvoie
422 validation_failed (dpop_required).
Changer d'organisation
Une application qui détient un jeton d'accès Front API pour l'utilisateur connecté (voir Jeton d'accès Front API)
fait passer l'utilisateur à une autre organisation sans écran. Envoyez le jeton dans Authorization: DPoP <token> avec une preuve
de la clé du jeton (avec ath), et dans le corps le flow organization_switch, les champs sans interface liés à DPoP ci-dessus
(client_id de l'application du jeton, redirect_uri, code_challenge, state, nonce, scope) et
organization, l'identifiant org_… d'une organisation issu de GET /fapi/v1/me/organizations.
La demande est traitée immédiatement avec la session du jeton, comme le serait une connexion qui réutilise la session : la
politique de l'organisation (MFA, limite d'inactivité, authentification unique, liste d'IP), le consentement et les documents juridiques en attente. La réponse est 201 avec une
transaction completed qui contient authorization_response ; échangez son code au point de terminaison de jeton avec votre
code_verifier et une preuve de la même clé. Les nouveaux jetons portent l'organisation dans org_id. Aucune transaction n'est laissée ouverte
et aucun cookie n'est défini.
{
"schema_version": 1,
"state": "completed",
"next_steps": [],
"authorization_response": { "code": "<code>", "state": "<state>", "iss": "https://example.keenauth.app" },
"expires_at": "2026-10-05T10:15:00Z"
}
| Statut | Code | Quand |
|---|---|---|
| 401 | unauthenticated |
Le jeton est invalide, expiré, révoqué ou non lié à une clé, son application n'est pas une application de première partie active, ou sa session a pris fin. |
| 422 | validation_failed |
flow n'est pas organization_switch, client_id n'est pas l'application du jeton, organization n'est pas un identifiant org_…, ou l'utilisateur ne peut pas basculer vers elle dans cette application (not_eligible). |
| 403 | authorization_failed |
L'organisation exige un écran que le changement ne peut pas afficher ; error est l'erreur OAuth (login_required, interaction_required, consent_required). Démarrez une nouvelle connexion avec organization renseigné. |
Un flow organization_switch sans le jeton renvoie 422 validation_failed (access_token_required).
Erreurs
| Statut | Code | Quand |
|---|---|---|
| 400 | malformed_request |
Idp-Client est absent ou le corps n'est pas un JSON valide. |
| 403 | origin_not_allowed |
Origin n'est pas l'hôte de connexion. |
| 403 | headless_not_allowed |
Une application tierce a tenté de démarrer un flux sans interface. |
| 404 | not_found |
L'hôte n'est l'hôte de connexion d'aucun environnement. |
| 422 | validation_failed |
client_id n'est pas une application de cet environnement, redirect_uri n'est pas enregistrée pour elle, ou un champ est invalide. |
| 401 | invalid_dpop_proof |
La preuve DPoP est absente, invalide ou réutilisée, ou l'hôte ne sert pas de transactions liées à DPoP. |
| 401 | use_dpop_nonce |
Signez une nouvelle preuve avec la valeur de l'en-tête de réponse DPoP-Nonce. |
| 503 | temporarily_unavailable |
Une dépendance est indisponible ; réessayez plus tard. |
Exemple
curl -X POST https://example.keenauth.app/fapi/v1/transactions \
-H "Idp-Client: my-app/1.0.0 (node/22.0.0)" \
-H "Origin: https://example.keenauth.app" \
-H "Content-Type: application/json" \
-c cookies.txt \
-d '{"client_id":"<client_id>","redirect_uri":"https://app.example.com/callback"}'
Données personnelles
Ce point de terminaison traite des données personnelles : le profil de l'utilisateur final. Données personnelles dans les API KeenAuth décrit ce qui est stocké, pendant combien de temps il est conservé et comment il est supprimé. N'envoyez aucune catégorie particulière de données personnelles (santé, données biométriques, religion, opinions politiques, orientation sexuelle) dans aucun champ.