API OAuth 2.0 Avanzato
Auris fornisce implementazioni delle specifiche OAuth 2.0 e OIDC avanzate per scenari enterprise. Queste funzionalità includono il Device Authorization Flow per dispositivi senza browser, il Token Exchange per impersonation e delegation, i token DPoP (Demonstrating Proof of Possession) vincolati al mittente, l’autenticazione CIBA (Client-Initiated Backchannel Authentication) e la valutazione del rischio con MFA adattivo.
Tutte le funzionalità avanzate OAuth 2.0 devono essere abilitate per ogni applicazione nella Console di Auris (Console > Applicazioni > [Nome App] > OAuth Avanzato) prima di poter essere usate.
Device Authorization Flow (RFC 8628)
Il Device Authorization Flow consente ai dispositivi con capacità di input limitate (smart TV, terminali CLI, apparecchi IoT) di ottenere token OAuth 2.0. Il dispositivo mostra un codice utente corto e un URL; l’utente completa l’autenticazione su un dispositivo separato.
/api/oauth/device-authorizeAvvia il Device Authorization Flow. Restituisce un device_code, un user_code da
mostrare all’utente e i metadati di polling.
Corpo della richiesta
{
"client_id": "app_abc123",
"scope": "openid profile email"
}Risposta di successo
{
"ok": true,
"data": {
"device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
"user_code": "WDJB-MJHT",
"verification_uri": "https://api.altovar.net/hosted/device",
"verification_uri_complete": "https://api.altovar.net/hosted/device?user_code=WDJB-MJHT",
"expires_in": 1800,
"interval": 5
}
}| Campo | Descrizione |
|---|---|
device_code | Codice opaco lungo per il dispositivo. Usato per il polling dell’endpoint token. Non mostrarlo mai all’utente. |
user_code | Codice breve leggibile (formato XXXX-XXXX) da mostrare sullo schermo del dispositivo. |
verification_uri | URL dove l’utente deve navigare sul suo device secondario. |
verification_uri_complete | Convenience URL con user_code pre-compilato (per QR code). |
expires_in | Secondi prima che il device_code scada (1800 = 30 minuti). |
interval | Secondi minimi da aspettare tra i tentativi di polling. Il polling più frequente restituisce slow_down. |
Codici di errore
| Codice | HTTP | Descrizione |
|---|---|---|
DEVICE_FLOW_DISABLED | 400 | Device Flow non abilitato per questa applicazione |
VALIDATION_ERROR | 400 | client_id mancante o non valido |
Polling per il Token
Una volta mostrato il user_code all’utente, il dispositivo deve fare polling sull’endpoint token finché l’utente autorizza la richiesta, il codice scade o l’utente nega l’accesso.
{
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
"device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
"client_id": "app_abc123"
}| Risposta polling | Descrizione |
|---|---|
AUTHORIZATION_PENDING | L’utente non ha ancora completato l’autorizzazione. Riprova dopo interval secondi. |
SLOW_DOWN | Stai facendo polling troppo frequentemente. Aumenta l’intervallo di polling di 5 secondi. |
EXPIRED_TOKEN | Il device_code è scaduto. Avvia un nuovo flusso. |
ACCESS_DENIED | L’utente ha negato la richiesta di autorizzazione. |
| Risposta token | L’utente ha autorizzato. Risposta token standard con access_token, refresh_token, id_token. |
La pagina di verifica ospitata da Auris è disponibile su /hosted/device. Mostra un form per inserire il codice utente, esegue l’autenticazione se necessario, e conferma l’autorizzazione del dispositivo.
Token Exchange (RFC 8693)
Il Token Exchange consente a un servizio di ottenere token agendo come un altro utente (impersonation) o per conto di un altro utente (delegation). Entrambi richiedono permessi espliciti e generano voci di audit log complete.
/api/auth/tokenRequires: impersonate:users o delegate:tokensScambia un token esistente con un nuovo token che rappresenta una diversa identità o contesto. Supporta sia il pattern di impersonation (agisce come un utente) che il pattern di delegation (agisce per conto di un utente).
Impersonation
Il servizio richiedente agisce completamente come l’utente target. Il token risultante ha come sub l’ID dell’utente target. Tutti gli eventi di audit mostrano l’impersonation.
{
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"subject_token": "eyJhbGciOiJSUzI1NiJ9...",
"subject_token_type": "urn:ietf:params:oauth:token-type:access_token",
"requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
"exchange_type": "impersonation",
"target_user_id": "usr_target123"
}Risposta — token standard con "sub": "usr_target123"
Delegation
Il servizio richiedente agisce per conto dell’utente originale. Il soggetto originale è preservato nel token. Il claim act identifica il principale che sta agendo.
{
"grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
"subject_token": "eyJhbGciOiJSUzI1NiJ9...",
"subject_token_type": "urn:ietf:params:oauth:token-type:access_token",
"requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
"exchange_type": "delegation"
}Payload JWT risultante
{
"sub": "usr_original123",
"act": {
"sub": "usr_acting_service456"
},
"scope": "read:data"
}Campi della richiesta
| Campo | Obbligatorio | Descrizione |
|---|---|---|
grant_type | Sì | Deve essere urn:ietf:params:oauth:grant-type:token-exchange |
subject_token | Sì | Il token di accesso dell’utente originale per conto del quale si agisce |
subject_token_type | Sì | Deve essere urn:ietf:params:oauth:token-type:access_token |
requested_token_type | Sì | Deve essere urn:ietf:params:oauth:token-type:access_token |
exchange_type | Sì | impersonation o delegation |
target_user_id | Per impersonation | Richiesto per impersonation; l’utente da impersonare |
scope | No | Sottoinsieme degli scope del token originale da includere nel nuovo token |
Codici di errore
| Codice | HTTP | Descrizione |
|---|---|---|
TOKEN_EXCHANGE_DISABLED | 400 | Token Exchange non abilitato per questa applicazione |
INVALID_SUBJECT_TOKEN | 401 | Il token soggetto non è valido o è scaduto |
TARGET_USER_NOT_FOUND | 404 | Il target_user_id non corrisponde a nessun utente esistente |
PERMISSION_DENIED | 403 | Permesso mancante (impersonate:users o delegate:tokens) |
SCOPE_EXCEEDS_ORIGINAL | 400 | I scope richiesti superano quelli del token soggetto originale |
DPoP — Demonstrating Proof of Possession (RFC 9449)
I token DPoP sono crittograficamente vincolati al client che li ha ottenuti. A differenza dei token Bearer standard, i token DPoP non possono essere usati da un attaccante che li intercetta perché le chiamate API richiedono una prova JWT fresca firmata con la chiave privata del client.
Come Funziona il DPoP
- Generazione delle chiavi: Il client genera una coppia di chiavi a curva ellittica (EC P-256 o RSA). La chiave privata non lascia mai il client.
- Creazione della prova: Per ogni richiesta, il client crea un JWT di prova DPoP firmato con la chiave privata, includendo il metodo HTTP, l’URL e un
jtiunivoco. - Binding del token: Il server valida la prova, estrae il thumbprint JWK e vincola il token emesso a quella chiave pubblica.
- Chiamate API: Le chiamate API successive richiedono sia il token DPoP che una nuova prova DPoP fresca per quella specifica richiesta.
Struttura della Prova DPoP
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik...Il JWT di prova DPoP ha la seguente struttura:
Header
{
"typ": "dpop+jwt",
"alg": "ES256",
"jwk": {
"kty": "EC",
"crv": "P-256",
"x": "f83OJ3D2xF1Bg8vub9tLe1gHMzV76e8Tus9uPHvRVEU",
"y": "x_FEzRu9m36HLN_tue659LNpXW6pCyStikYjKIWI5a0"
}
}Payload
{
"htm": "POST",
"htu": "https://api.altovar.net/api/auth/token",
"iat": 1707300000,
"jti": "unique-id-per-request-abc123",
"nonce": "server-provided-nonce"
}| Campo | Descrizione |
|---|---|
htm | Metodo HTTP della richiesta (GET, POST, ecc.) |
htu | URL completo della richiesta senza query string |
iat | Issued At — il clock skew consentito è 30 secondi |
jti | Identificativo univoco per questa prova specifica (previene il replay) |
nonce | Nonce fornito dal server (obbligatorio quando il server lo include nella risposta) |
Token DPoP nella Risposta
Quando si ottiene un token usando DPoP, la risposta include "token_type": "DPoP" anziché "Bearer". Il JWT del token di accesso contiene un claim cnf.jkt con il JWK thumbprint:
{
"sub": "usr_abc123",
"cnf": {
"jkt": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I"
}
}Per usare un token DPoP, includi l’intestazione Authorization: DPoP <token> insieme a un’intestazione DPoP: <fresh-proof>.
Gestione del Nonce
Il server può richiedere un nonce per prevenire replay. Includi il nonce nelle prove DPoP successive:
DPoP-Nonce: eyJ...server-issued-nonce...Questo nonce deve essere incluso nel claim nonce del tuo prossimo JWT di prova DPoP. Se invii una prova senza nonce quando è richiesto, riceverai un errore use_dpop_nonce con un nonce fresco nell’intestazione della risposta.
Codici di errore
| Codice | HTTP | Descrizione |
|---|---|---|
INVALID_DPOP_PROOF | 401 | La prova DPoP non è valida (firma non valida, scaduta, jti riusato) |
DPOP_NONCE_REQUIRED | 401 | È richiesto un nonce — vedi l’intestazione DPoP-Nonce nella risposta |
DPOP_JKT_MISMATCH | 401 | La chiave pubblica nella prova non corrisponde al thumbprint nel token |
DPOP_DISABLED | 400 | DPoP non abilitato per questa applicazione |
CIBA — Autenticazione Backchannel (Client-Initiated Backchannel Authentication)
CIBA consente a un servizio di avviare un’autenticazione in background su un dispositivo o canale separato (come una notifica push su mobile) senza reindirizzare il browser. Utile per call center, autenticazione a distanza e app su dispositivi separati.
/api/oauth/backchannel/authorizeRequires: manage:ciba_configAvvia un flusso di autenticazione backchannel per l’utente identificato. Auris invia una notifica di autenticazione all’utente (push, notifica in-app, ecc.). Il servizio fa polling o aspetta un callback per il token.
Corpo della richiesta
{
"client_id": "app_abc123",
"client_secret": "app_secret_xyz",
"scope": "openid profile",
"login_hint": "[email protected]",
"binding_message": "Autorizza pagamento $50 a Jane",
"requested_expiry": 300
}| Campo | Obbligatorio | Descrizione |
|---|---|---|
client_id | Sì | L’identificativo dell’applicazione |
client_secret | Sì | Il segreto dell’applicazione |
scope | Sì | Scope OAuth da richiedere |
login_hint | Sì | Email o ID dell’utente da autenticare |
binding_message | No | Breve messaggio leggibile mostrato all’utente per associare la richiesta a un’azione. Massimo 256 caratteri. |
requested_expiry | No | Secondi di validità della richiesta. Default 300, massimo 600. |
Risposta di successo
{
"ok": true,
"data": {
"auth_req_id": "1c266114-a1be-4252-8ad1-04986c5b9ac9",
"expires_in": 300,
"interval": 5
}
}Modi di Notifica
Il modo in cui il tuo servizio riceve il risultato dell’autenticazione dipende dalla modalità CIBA configurata per l’applicazione:
| Modalità | Comportamento |
|---|---|
poll | Il tuo servizio fa polling sull’endpoint token con auth_req_id |
ping | Auris invia una HTTP callback alla tua applicazione (notification_endpoint) quando l’utente risponde; poi il tuo servizio chiama l’endpoint token |
push | Auris invia il token direttamente alla tua applicazione (notification_endpoint) dopo che l’utente risponde |
Polling CIBA
Per la modalità poll, esegui polling sull’endpoint token:
{
"grant_type": "urn:openid:params:grant-type:ciba",
"auth_req_id": "1c266114-a1be-4252-8ad1-04986c5b9ac9",
"client_id": "app_abc123",
"client_secret": "app_secret_xyz"
}Le risposte di polling funzionano allo stesso modo del Device Flow: AUTHORIZATION_PENDING, SLOW_DOWN, EXPIRED_TOKEN, ACCESS_DENIED, o un token di successo.
Codici di errore
| Codice | HTTP | Descrizione |
|---|---|---|
CIBA_DISABLED | 400 | CIBA non abilitato per questa applicazione |
USER_NOT_FOUND | 404 | L’utente specificato in login_hint non esiste |
NOTIFICATION_FAILED | 502 | Auris non ha potuto inviare la notifica al dispositivo dell’utente |
BINDING_MESSAGE_TOO_LONG | 400 | Il binding_message supera i 256 caratteri |
Valutazione del Rischio e MFA Adattivo
Auris valuta il rischio di ogni evento di autenticazione in tempo reale. Sulla base del punteggio di rischio, può consentire il login, richiedere un passaggio MFA aggiuntivo, o bloccare completamente il tentativo di autenticazione.
Fattori di Rischio
Ogni fattore contribuisce per il 20% al punteggio di rischio complessivo:
| Fattore | Descrizione |
|---|---|
| Reputazione IP | Controlla se l’IP di origine è un IP malevolo noto, una VPN, un proxy o una rete datacenter |
| Device Trust | Determina se il fingerprint del dispositivo è stato visto in precedenza per questo utente |
| Anomalia Geografica | Rileva il viaggio impossibile e le posizioni geografiche insolite |
| Comportamento | Analizza i pattern di login come l’orario del giorno insolito e tentativi di accesso falliti ripetuti |
| Sensibilità dell’Azione | Quanto è sensibile l’azione richiesta (operazione normale vs. operazione critica di sicurezza) |
Livelli di Rischio
| Livello | Punteggio | Azione predefinita |
|---|---|---|
LOW | 0–30 | Consenti il login |
MEDIUM | 31–60 | Richiedi MFA |
HIGH | 61–80 | Richiedi MFA forte (hardware key o biometria) |
CRITICAL | 81–100 | Blocca il login |
Claim JWT ACR e AMR
I token Auris includono claim standard OIDC che descrivono come l’utente si è autenticato:
Claim acr (Authentication Context Class Reference)
| Valore | Descrizione |
|---|---|
urn:auris:acr:pwd | Solo autenticazione con password |
urn:auris:acr:mfa | Autenticazione multi-fattore completata |
urn:auris:acr:strong | MFA forte con hardware key o biometria |
Claim amr (Authentication Methods References)
Array di metodi usati durante l’autenticazione: pwd, otp, sms, webauthn, social, magic_link, sso
{
"sub": "usr_abc123",
"acr": "urn:auris:acr:mfa",
"amr": ["pwd", "otp"]
}API Valutazione del Rischio
/api/auth/risk/assessmentsRequires: view:risk_assessmentsElenca le valutazioni del rischio di autenticazione con filtri. Ogni voce include il punteggio di rischio, i fattori contribuenti e l’azione intrapresa dal motore di rischio.
Parametri query
| Parametro | Tipo | Descrizione |
|---|---|---|
page | number | Numero di pagina (default: 1) |
limit | number | Risultati per pagina (default: 20, max: 100) |
userId | string | Filtra per ID utente specifico |
level | string | Filtra per livello di rischio: LOW, MEDIUM, HIGH, CRITICAL |
dateFrom | string | Data di inizio ISO 8601 |
dateTo | string | Data di fine ISO 8601 |
Risposta di esempio
{
"ok": true,
"data": [
{
"id": "risk_abc123",
"userId": "usr_xyz789",
"score": 72,
"level": "HIGH",
"factors": {
"ipReputation": 20,
"deviceTrust": 0,
"geoAnomaly": 20,
"behavior": 12,
"actionSensitivity": 20
},
"actionTaken": "step_up_mfa",
"ipAddress": "203.0.113.42",
"country": "IT",
"city": "Milano",
"createdAt": "2025-02-18T14:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 142,
"pages": 8
}
}Regole di Rischio Personalizzate
Puoi estendere il motore di valutazione del rischio con regole custom che sovrascrivono o aumentano il comportamento predefinito.
/api/auth/risk/rulesRequires: manage:risk_rulesElenca tutte le regole di rischio custom configurate per il tenant.
/api/auth/risk/rulesRequires: manage:risk_rulesCrea una nuova regola di rischio custom. Le regole vengono valutate ad ogni evento di autenticazione.
Corpo della richiesta
{
"name": "Blocca accessi da proxy noti",
"condition": {
"field": "ipReputation.isProxy",
"operator": "equals",
"value": true
},
"action": "block",
"scoreModifier": 50,
"isActive": true
}| Campo | Obbligatorio | Descrizione |
|---|---|---|
name | Sì | Nome descrittivo per la regola |
condition | Sì | La condizione da valutare (vedi tabella campi sotto) |
action | Sì | Azione: allow, step_up_mfa, block, log |
scoreModifier | No | Aggiunge questo valore (0–100) al punteggio di rischio quando la condizione è vera |
isActive | Sì | Se la regola è attiva |
Campi condizione disponibili
| Campo | Tipo | Descrizione |
|---|---|---|
ipReputation.isVpn | boolean | L’IP è una VPN |
ipReputation.isProxy | boolean | L’IP è un proxy |
ipReputation.isDatacenter | boolean | L’IP è un range datacenter |
deviceTrust.isNewDevice | boolean | Il dispositivo non è mai stato visto prima per questo utente |
geoAnomaly.isNewCountry | boolean | Login da un paese mai visto prima per questo utente |
geoAnomaly.distance | number | Distanza in km dalla posizione di login precedente |
behavior.unusualTime | boolean | Login a un orario del giorno insolito per questo utente |
behavior.failedAttempts | number | Numero di tentativi falliti recenti |
Operatori disponibili
equals, not_equals, greater_than, less_than, contains, in
/api/auth/risk/rules/[id]Requires: manage:risk_rulesAggiorna una regola di rischio esistente. Accetta gli stessi campi della creazione. Puoi aggiornare parzialmente (solo i campi specificati vengono modificati).
/api/auth/risk/rules/[id]Requires: manage:risk_rulesElimina permanentemente una regola di rischio custom. L’eliminazione è irreversibile.
Riferimento Permessi
| Permesso | Descrizione |
|---|---|
manage:device_codes | Abilita e usa il Device Authorization Flow |
impersonate:users | Esegue Token Exchange con exchange_type: "impersonation" |
delegate:tokens | Esegue Token Exchange con exchange_type: "delegation" |
manage:dpop_config | Configura le impostazioni DPoP per le applicazioni |
manage:ciba_config | Configura e avvia richieste di autenticazione CIBA |
view:risk_assessments | Legge log e dati di valutazione del rischio |
manage:risk_rules | Crea, aggiorna ed elimina regole di rischio custom |
manage:advanced_oauth | Configurazione OAuth 2.0 avanzato completa |
Correlati
- Concetto DPoP — Come funziona il binding della chiave DPoP
- Concetto Device Flow — Device Authorization Flow spiegato
- Concetto CIBA — Autenticazione backchannel
- Concetto Token Exchange — Impersonation e delegation
- Uso di DPoP — Implementazione dei token DPoP
- Device Flow — Guida al Device Flow
- CIBA — Configurazione dell’autenticazione backchannel
- Token Exchange — Guida all’exchange dei token
- OAuth Avanzato Admin — Configurazione dalla Console