
# Obtenir l'état de connexion d'un utilisateur

`GET /v1/users/{user_id}/sign-in-state` · permission `users:read`

Renvoie les informations dont votre équipe de support a besoin lorsqu'un utilisateur ne peut pas se connecter : les verrouillages de compte ouverts de l'utilisateur, les compteurs d'échecs encore actifs sur chaque chemin de connexion, et la dernière authentification réussie. L'appel est en lecture seule ; rien n'est modifié et aucun enregistrement d'audit n'est écrit. Pour supprimer les verrouillages, utilisez [`POST /v1/users/{user_id}:unlock`](unlock.md).

La réponse ne contient jamais l'identifiant interne du compteur, une adresse e-mail, une adresse IP, un appareil ni un identifiant de session. Pour les sessions de l'utilisateur, utilisez [`GET /v1/users/{user_id}/sessions`](list-sessions.md).

## Périmètre de l'organisation

Transmettez `org_id` pour construire une vue de diagnostic des membres destinée à un administrateur d'organisation. La clé doit alors aussi disposer de l'autorisation `organizations:read` ; sans elle, la requête échoue avec `403 insufficient_permissions` avant toute lecture. Si l'utilisateur n'est pas membre de cette organisation (aucune adhésion `invited`, `active` ou `suspended`), la requête échoue avec `404 not_found`, la même réponse que pour un utilisateur inconnu. Si l'utilisateur est membre, `last_sign_in` provient uniquement des sessions dans le contexte de cette organisation, et `failures` est toujours un tableau vide, car les compteurs d'échecs ne sont rattachés à aucune organisation. Les verrouillages sont tout de même renvoyés, car un verrouillage bloque la connexion du compte dans tous les contextes. Sans `org_id`, la réponse est inchangée.

## Requête

| Paramètre | Dans | Obligatoire | Description |
|---|---|---|---|
| `user_id` | chemin | oui | Identifiant de l'utilisateur, préfixé `usr_`. |
| `org_id` | requête | non | Identifiant de l'organisation, préfixé `org_`. Limite la vue à cette organisation ; voir [Périmètre de l'organisation](#périmètre-de-lorganisation). Nécessite `organizations:read`. |

## Réponse

`200 OK`.

```json
{
  "locked": true,
  "locked_until": "2026-10-20T10:00:00Z",
  "locks": [
    {"id": "lck_0a1b2c3d4e5f6g7h8j9k0m1n2p", "path": "password",
     "locked_at": "2026-10-20T09:45:00Z", "expires_at": "2026-10-20T10:00:00Z"}
  ],
  "failures": [
    {"path": "totp", "count": 3, "window_ends_at": "2026-10-20T09:55:00Z"}
  ],
  "last_sign_in": {"authenticated_at": "2026-10-19T18:12:04Z", "amr": ["pwd", "otp"], "country": "DE"}
}
```

| Champ | Description |
|---|---|
| `locked` | `true` lorsqu'au moins un chemin de connexion est verrouillé. |
| `locked_until` | Moment où se termine le dernier verrouillage ouvert ; `null` sans verrouillage. |
| `locks` | Verrouillages ouverts, du plus ancien au plus récent, au maximum un par chemin (`password`, `totp`, `sms_2fa`, `email_2fa`, `otp`, `recovery_code`). |
| `failures` | Tentatives échouées depuis le dernier succès ou le dernier verrouillage, par chemin, pendant que la fenêtre de comptage est active. Après `window_ends_at`, le compteur repart de zéro. La fenêtre du mot de passe correspond à `brute_force.window_minutes` de l'environnement. |
| `last_sign_in` | La plus récente authentification réussie parmi les sessions encore conservées : `authenticated_at` (une réauthentification dans la même session la fait avancer), les méthodes d'authentification (`amr`, RFC 8176) et le dernier pays connu de la session (`null` si inconnu). `null` lorsqu'aucune session n'est conservée : l'utilisateur ne s'est jamais connecté, ou la dernière session s'est terminée il y a plus de 30 jours. |

## Erreurs

Chaque erreur est un corps `application/problem+json` avec un `code` stable.

| HTTP | `code` | Quand |
|---|---|---|
| 404 | `not_found` | L'utilisateur n'existe pas dans cet environnement (ou l'identifiant est mal formé), ou `org_id` est fourni et l'utilisateur n'est pas membre de cette organisation. |
| 401 | `unauthenticated` | La clé d'API est absente, invalide ou révoquée. |
| 403 | `insufficient_permissions` | La clé ne dispose pas de l'autorisation `users:read`, ou `org_id` est fourni et la clé ne dispose pas de `organizations:read`. |
| 429 | `rate_limited` | La limite de débit a été dépassée ; respectez `Retry-After`. |
| 503 | `service_unavailable` | Une dépendance est temporairement indisponible ; réessayez plus tard. |

## Exemple

```bash
curl https://api.eu.keenauth.com/v1/users/usr_0a1b2c3d4e5f6g7h8j9k0m1n2p/sign-in-state \
  -H "Authorization: Bearer $KEENAUTH_SECRET_KEY"
```

CLI : `keenauth users sign-in-state usr_0a1b2c3d4e5f6g7h8j9k0m1n2p`
