
# Recupera lo stato di accesso di un utente

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

Restituisce ciò che il tuo team di supporto ti serve quando un utente non riesce ad accedere: i blocchi dell'account aperti, i conteggi dei tentativi falliti ancora attivi su ciascun percorso di accesso e l'ultima autenticazione riuscita. La chiamata è di sola lettura; non modifica nulla e non scrive alcun record di audit. Per rimuovere i blocchi, usa [`POST /v1/users/{user_id}:unlock`](unlock.md).

La risposta non include mai l'identificativo interno del soggetto del contatore, un indirizzo email, un indirizzo IP, un dispositivo o un ID di sessione. Per le sessioni dell'utente, usa [`GET /v1/users/{user_id}/sessions`](list-sessions.md).

## Ambito organizzazione

Passa `org_id` per ottenere una vista diagnostica dei membri per un admin dell'organizzazione. La chiave deve avere anche l'autorizzazione `organizations:read`; senza di essa la richiesta fallisce con `403 insufficient_permissions` prima che venga letto qualcosa. Se l'utente non è membro di quell'organizzazione (nessuna appartenenza `invited`, `active` o `suspended`), la richiesta fallisce con `404 not_found`, la stessa risposta data per un utente sconosciuto. Se l'utente è membro, `last_sign_in` proviene solo dalle sessioni nel contesto di quell'organizzazione, e `failures` è sempre un array vuoto, perché i contatori dei tentativi falliti non sono attribuiti ad alcuna organizzazione. I blocchi vengono comunque restituiti, dato che un blocco interrompe l'accesso dell'account in ogni contesto. Senza `org_id` la risposta resta invariata.

## Richiesta

| Parametro | In | Obbligatorio | Descrizione |
|---|---|---|---|
| `user_id` | path | sì | ID utente, con prefisso `usr_`. |
| `org_id` | query | no | ID organizzazione, con prefisso `org_`. Limita la vista a quell'organizzazione; vedi [Ambito organizzazione](#ambito-organizzazione). Richiede `organizations:read`. |

## Risposta

`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"}
}
```

| Campo | Descrizione |
|---|---|
| `locked` | `true` quando almeno un percorso di accesso è bloccato. |
| `locked_until` | Quando termina l'ultimo blocco aperto; `null` senza blocchi. |
| `locks` | Blocchi aperti, dal più vecchio, al massimo uno per percorso (`password`, `totp`, `sms_2fa`, `email_2fa`, `otp`, `recovery_code`). |
| `failures` | Tentativi falliti dall'ultimo successo o dall'ultimo blocco, per percorso, mentre la finestra di conteggio è attiva. Dopo `window_ends_at` il conteggio riparte da zero. La finestra per la password è `brute_force.window_minutes` dell'ambiente. |
| `last_sign_in` | L'autenticazione riuscita più recente tra le sessioni ancora conservate: `authenticated_at` (una riautenticazione nella stessa sessione la sposta in avanti), i metodi di autenticazione (`amr`, RFC 8176) e l'ultimo paese noto della sessione (`null` se sconosciuto). `null` quando non è conservata alcuna sessione: l'utente non ha mai effettuato l'accesso, oppure l'ultima sessione è terminata più di 30 giorni fa. |

## Errori

Ogni errore è un corpo `application/problem+json` con un `code` stabile.

| HTTP | `code` | Quando |
|---|---|---|
| 404 | `not_found` | L'utente non esiste in questo ambiente (o l'ID è malformato), oppure è stato passato `org_id` e l'utente non è membro di quell'organizzazione. |
| 401 | `unauthenticated` | La chiave API manca, non è valida o è stata revocata. |
| 403 | `insufficient_permissions` | La chiave non ha l'autorizzazione `users:read`, oppure è stato passato `org_id` e la chiave non ha `organizations:read`. |
| 429 | `rate_limited` | È stato superato il limite di richieste; rispetta `Retry-After`. |
| 503 | `service_unavailable` | Una dipendenza non è disponibile temporaneamente; riprova più tardi. |

## Esempio

```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`
