
# Exécuter une étape de connexion

`POST /fapi/v1/transactions/current/steps/{step}` · appelé depuis l'hôte de connexion de l'environnement

Exécute une étape de la transaction en cours. Cette version accepte les étapes `identifier` et `password`. Chaque étape d'identifiants en échec renvoie le même `401 invalid_credentials`, de sorte que la réponse ne révèle jamais si un compte existe. Lorsque l'étape du mot de passe termine la transaction, les cookies de session `__Host-idp_session` (et, si nécessaire, `__Host-idp_device`) sont définis et le cookie de transaction est supprimé.

## Requête

En-têtes :

| En-tête | Obligatoire | Description |
| --- | --- | --- |
| `Idp-Client` | oui | Identifiant du SDK. |
| `Origin` | oui | Doit être exactement `https://<sign-in host>`. |
| `Idp-Csrf-Token` | oui | Le `csrf_token` de l'objet de transaction. |

Chemin : `step`, le nom de l'étape (`identifier`, `password`, `sso_start`).

À l'étape `otp_send`, `next_steps[].methods` liste les méthodes sans mot de passe autorisées par la politique effective (`email_otp`, `magic_link`) ; un client ne propose que celles-ci.

Corps (les champs dépendent de l'étape ; `next_steps[].fields` les énumère) :

| Champ | Type | Description |
| --- | --- | --- |
| `identifier` | chaîne | Adresse e-mail, numéro de téléphone ou nom d'utilisateur (étape `identifier`), 320 caractères au maximum. |
| `password` | chaîne | Le mot de passe (étape `password`), 128 caractères au maximum. |
| `connection_id` | chaîne | Une valeur `sso_connections[].connection_id` (étape `sso_start`). |

## Réponse

`200 OK` avec la transaction après l'étape. Une transaction `completed` n'a pas de `csrf_token`.

Lorsque l'environnement exige un second facteur et que l'utilisateur n'en a pas encore, un utilisateur encore dans le `mfa.enrollment_grace_days` de l'environnement se connecte malgré tout et la réponse `completed` contient `mfa_enrollment` : `required_by` (RFC 3339, fin de la période de grâce, calculée par le serveur) et `methods` (`webauthn`, `totp` : les facteurs que l'utilisateur peut inscrire maintenant, dans l'ordre de l'écran). Affichez la date et laissez l'utilisateur continuer ; l'inscription se fait dans les paramètres du compte. Le champ est absent lorsqu'il n'y a pas de période de grâce, que l'utilisateur respecte la politique, ou que l'inscription est exigée immédiatement. Le `min_acr` d'une application et le `acr_values` demandé ne sont jamais reportés par la période de grâce.

## SSO d'entreprise (découverte du domaine)

Lorsque l'étape `identifier` reçoit une adresse e-mail dont le domaine appartient à une connexion d'entreprise, la connexion se poursuit avec cette connexion. Seule la partie après `@` est utilisée pour la découverte.

- Une seule connexion : la transaction passe à `federated_redirect` et la réponse contient `redirect_url`, l'adresse de démarrage du fournisseur d'identité. Naviguez vers cette adresse dans la fenêtre de premier niveau. L'adresse contient un jeton à usage unique : ne le stockez pas et ne le journalisez pas.
- Plusieurs connexions : la transaction reste dans `identifier_pending` et la réponse liste `sso_connections` (`connection_id`, `display_name`, `protocol`). Affichez `display_name` sous forme de texte et envoyez le choix de l'utilisateur avec l'étape `sso_start` (`identifier` et `connection_id`). Une connexion non proposée pour le domaine renvoie `422 validation_failed`.
- Aucune connexion, ou découverte temporairement indisponible : la connexion normale se poursuit, de sorte qu'une panne ne bloque jamais les autres méthodes de connexion. `sso_start` est un choix explicite et renvoie `503 temporarily_unavailable` à la place.

Lorsque la demande de connexion désigne une organisation qui exige le SSO, la transaction ne propose que les connexions de cette organisation : les étapes du mot de passe et du code par e-mail ne sont pas proposées, et la clé d'accès ne reste disponible que si l'organisation dispose de comptes d'urgence (break-glass). La création de la transaction démarre déjà l'unique connexion (`federated_redirect` avec `redirect_url`) ou en liste plusieurs dans `sso_connections` ; envoyez le choix avec `sso_start` et `connection_id` seuls, `identifier` est facultatif ici. Sous cette exigence, la découverte ne revient pas à d'autres méthodes : lorsque la connexion d'entreprise est inaccessible, l'étape renvoie `503 temporarily_unavailable`. Il en va de même lorsque le domaine de l'e-mail appartient à une organisation qui exige le SSO pour ses domaines vérifiés.

Après le fournisseur d'identité, le navigateur revient vers `/u/sso/complete` sur l'hôte de connexion ; la page hébergée termine la connexion.

## Lier la connexion d'entreprise à un compte existant

Lorsqu'une connexion d'entreprise ne garantit pas les adresses e-mail et que l'adresse qu'elle affirme est déjà vérifiée sur un compte de l'environnement, la connexion d'entreprise n'ouvre pas de session. Le navigateur revient vers la page de connexion hébergée avec une nouvelle transaction dont l'objet contient `account_link` : `connection_name` et, lorsque la connexion appartient à une organisation, `organization_name`. Indiquez à l'utilisateur qu'il possède déjà un compte et qu'il doit s'y connecter pour lier la connexion ; ne nommez jamais le compte. Dans cette transaction, `sso_start` et `magic_link` ne sont pas proposés, et l'étape `identifier` n'oriente pas vers une connexion d'entreprise.

L'utilisateur se connecte au compte existant avec ses propres méthodes ; un utilisateur qui a un second facteur inscrit doit le fournir. L'étape qui termine la transaction n'ouvre aucune session : la connexion est liée au compte, et la réponse est une nouvelle transaction en `federated_redirect` avec `redirect_url` pour la même connexion. Naviguez vers cette transaction dans la fenêtre de premier niveau ; la connexion d'entreprise se termine alors normalement. Si la connexion d'entreprise ne peut pas démarrer, la nouvelle transaction est `identifier_pending` et une connexion ordinaire suit.

Une finalisation avec un autre compte, sans le second facteur inscrit, ou avec une connexion plus ancienne que la demande de liaison, ne lie rien et n'ouvre aucune session : `409 transaction_state_conflict`. Une demande de liaison expirée (10 minutes) ou déjà utilisée renvoie `410 transaction_expired`. Une demande de liaison est utilisée une seule fois, quel que soit le résultat. Pour refuser, appelez `POST /fapi/v1/transactions/current:cancel`.

## Politique de l'organisation

Lorsque la demande d'autorisation est liée à une organisation, la politique de connexion de l'organisation est vérifiée à nouveau après le premier facteur et juste avant l'ouverture de la session :

- L'adresse IP du client ne figure pas dans la liste d'autorisation de l'organisation : `403 ip_not_allowed`.
- Les facteurs de la transaction ne respectent pas la politique de l'organisation (une méthode que l'organisation n'autorise pas, un facteur manquant, ou une clé de sécurité ou une clé d'accès hors de la liste d'AAGUID autorisés par l'organisation) : `403 no_allowed_method`.
- La politique de l'organisation ne peut pas être lue : `503 temporarily_unavailable`. La connexion échoue en mode sécurisé et ne continue jamais sans la politique.

Aucune session n'est ouverte. Un refus lors de la finalisation de la transaction supprime le cookie de transaction ; un `503` après le premier facteur laisse la transaction en place, et l'étape peut être relancée. Le corps d'erreur ne nomme jamais l'organisation, l'utilisateur ni l'adresse IP.

## Transactions sans interface liées à DPoP

Pour une transaction démarrée avec un en-tête `DPoP`, envoyez une nouvelle preuve avec la même clé (`htm` `POST`, `htu` l'URL de l'étape) au lieu de `Idp-Csrf-Token` ; aucun cookie n'est utilisé. L'étape qui termine la transaction renvoie `authorization_response` une seule fois :

```json
{
  "state": "completed",
  "authorization_response": { "code": "<code>", "state": "<your state>", "iss": "https://example.keenauth.app" },
  "next_steps": [],
  "schema_version": 1,
  "expires_at": "2026-11-02T10:15:00Z"
}
```

Vérifiez que `state` et `iss` correspondent, puis échangez le code à `/oauth2/token` avec votre `code_verifier` et une preuve DPoP issue de la même clé. Une preuve issue d'une autre clé renvoie `invalid_grant`. Si la demande d'autorisation ne peut pas aboutir à un code (consentement, conditions légales, choix d'organisation ou nouvelle connexion nécessaires, ou accès refusé), l'étape renvoie `403 authorization_failed` et le membre `error` contient le code d'erreur OAuth ; aucun code n'est émis.

## Erreurs

| Statut | Code | Quand |
| --- | --- | --- |
| 401 | `invalid_credentials` | L'identifiant ou le mot de passe n'est pas accepté. |
| 403 | `origin_not_allowed` | `Origin` ou `Idp-Csrf-Token` est absent ou incorrect. |
| 403 | `ip_not_allowed` | L'adresse IP du client ne figure pas dans la liste d'autorisation de l'organisation. |
| 403 | `no_allowed_method` | La connexion ne respecte pas la politique de l'organisation. |
| 403 | `test_feature_not_in_production` | `otp_verify` ou `email_2fa` a reçu le code de test fixe `424242` dans un environnement de production. La tentative est comptée comme un code erroné. |
| 404 | `not_found` | Le nom de l'étape n'est pas connu. |
| 409 | `transaction_state_conflict` | L'étape n'est pas disponible dans l'état actuel. |
| 409 | `session_limit_reached` | L'utilisateur a atteint la limite de sessions et les nouvelles sessions sont refusées. |
| 410 | `transaction_expired` | La transaction est terminée. |
| 422 | `validation_failed` | Un champ est absent ou invalide. |
| 503 | `temporarily_unavailable` | `sso_start` n'a pas pu joindre la connexion d'entreprise, ou la politique de l'organisation n'a pas pu être lue ; réessayez. |
| 401 | `invalid_dpop_proof` | La preuve `DPoP` est absente, invalide ou réutilisée. |
| 403 | `authorization_failed` | La transaction liée à DPoP s'est terminée, mais sa demande d'autorisation s'est achevée sans code. |

## Exemple

```bash
curl -X POST https://example.keenauth.app/fapi/v1/transactions/current/steps/identifier \
  -H "Idp-Client: my-app/1.0.0 (node/22.0.0)" \
  -H "Origin: https://example.keenauth.app" \
  -H "Idp-Csrf-Token: $CSRF_TOKEN" \
  -H "Content-Type: application/json" \
  -b cookies.txt \
  -d '{"identifier":"jane@example.com"}'
```

## Données personnelles

Ce point de terminaison traite des données personnelles : profil de l'utilisateur final et identifiants. [Données personnelles dans les API KeenAuth](/docs/policies/personal-data) décrit ce qui est stocké, la durée de conservation et la suppression. Ne transmettez aucune catégorie particulière de données personnelles (santé, données biométriques, religion, opinions politiques, orientation sexuelle) dans aucun champ.
