API OAuth 2.0 Avancé
Auris fournit des implémentations des spécifications OAuth 2.0 et OIDC avancées pour les scénarios enterprise. Ces fonctionnalités incluent le Device Authorization Flow pour les appareils sans navigateur, le Token Exchange pour l’impersonation et la délégation, les tokens DPoP (Demonstrating Proof of Possession) liés à l’expéditeur, l’authentification CIBA (Client-Initiated Backchannel Authentication) et l’évaluation du risque avec MFA adaptatif.
Toutes les fonctionnalités OAuth 2.0 avancées doivent être activées pour chaque application dans la Console Auris (Console > Applications > [Nom App] > OAuth Avancé) avant de pouvoir être utilisées.
Device Authorization Flow (RFC 8628)
Le Device Authorization Flow permet aux appareils avec des capacités d’entrée limitées (smart TV, terminaux CLI, appareils IoT) d’obtenir des tokens OAuth 2.0. L’appareil affiche un code utilisateur court et une URL ; l’utilisateur complète l’authentification sur un appareil séparé.
/api/oauth/device-authorizeLance le Device Authorization Flow. Retourne un device_code, un user_code à
afficher à l’utilisateur et les métadonnées de polling.
Corps de la requête
{
"client_id": "app_abc123",
"scope": "openid profile email"
}Réponse de succès
{
"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
}
}| Champ | Description |
|---|---|
device_code | Code opaque long pour l’appareil. Utilisé pour le polling de l’endpoint token. Ne l’affiche jamais à l’utilisateur. |
user_code | Code court lisible (format XXXX-XXXX) à afficher sur l’écran de l’appareil. |
verification_uri | URL où l’utilisateur doit naviguer sur son appareil secondaire. |
verification_uri_complete | URL pratique avec user_code pré-rempli (pour QR code). |
expires_in | Secondes avant l’expiration du device_code (1800 = 30 minutes). |
interval | Secondes minimum à attendre entre les tentatives de polling. Un polling plus fréquent retourne slow_down. |
Codes d’erreur
| Code | HTTP | Description |
|---|---|---|
DEVICE_FLOW_DISABLED | 400 | Device Flow non activé pour cette application |
VALIDATION_ERROR | 400 | client_id manquant ou invalide |
Polling pour le Token
Une fois le user_code affiché à l’utilisateur, l’appareil doit effectuer un polling sur l’endpoint token jusqu’à ce que l’utilisateur autorise la demande, que le code expire ou que l’utilisateur refuse l’accès.
{
"grant_type": "urn:ietf:params:oauth:grant-type:device_code",
"device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
"client_id": "app_abc123"
}| Réponse polling | Description |
|---|---|
AUTHORIZATION_PENDING | L’utilisateur n’a pas encore complété l’autorisation. Réessaie après interval secondes. |
SLOW_DOWN | Tu fais le polling trop fréquemment. Augmente l’intervalle de polling de 5 secondes. |
EXPIRED_TOKEN | Le device_code a expiré. Lance un nouveau flux. |
ACCESS_DENIED | L’utilisateur a refusé la demande d’autorisation. |
| Réponse token | L’utilisateur a autorisé. Réponse token standard avec access_token, refresh_token, id_token. |
La page de vérification hébergée par Auris est disponible sur /hosted/device. Elle affiche un formulaire pour saisir le code utilisateur, effectue l’authentification si nécessaire, et confirme l’autorisation de l’appareil.
Token Exchange (RFC 8693)
Le Token Exchange permet à un service d’obtenir des tokens en agissant comme un autre utilisateur (impersonation) ou pour le compte d’un autre utilisateur (délégation). Les deux nécessitent des permissions explicites et génèrent des entrées complètes dans le journal d’audit.
/api/auth/tokenRequires: impersonate:users ou delegate:tokensÉchange un token existant contre un nouveau token représentant une identité ou un contexte différent. Supporte à la fois le pattern d’impersonation (agir comme un utilisateur) et le pattern de délégation (agir pour le compte d’un utilisateur).
Impersonation
Le service demandeur agit entièrement comme l’utilisateur cible. Le token résultant a l’ID de l’utilisateur cible comme sub. Tous les événements d’audit montrent 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"
}Réponse — token standard avec "sub": "usr_target123"
Délégation
Le service demandeur agit pour le compte de l’utilisateur original. Le sujet original est préservé dans le token. Le claim act identifie le principal qui agit.
{
"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 résultant
{
"sub": "usr_original123",
"act": {
"sub": "usr_acting_service456"
},
"scope": "read:data"
}Champs de la requête
| Champ | Obligatoire | Description |
|---|---|---|
grant_type | Oui | Doit être urn:ietf:params:oauth:grant-type:token-exchange |
subject_token | Oui | Le token d’accès de l’utilisateur original pour le compte duquel on agit |
subject_token_type | Oui | Doit être urn:ietf:params:oauth:token-type:access_token |
requested_token_type | Oui | Doit être urn:ietf:params:oauth:token-type:access_token |
exchange_type | Oui | impersonation ou delegation |
target_user_id | Pour impersonation | Requis pour l’impersonation ; l’utilisateur à impersonner |
scope | Non | Sous-ensemble des scopes du token original à inclure dans le nouveau token |
Codes d’erreur
| Code | HTTP | Description |
|---|---|---|
TOKEN_EXCHANGE_DISABLED | 400 | Token Exchange non activé pour cette application |
INVALID_SUBJECT_TOKEN | 401 | Le token sujet n’est pas valide ou a expiré |
TARGET_USER_NOT_FOUND | 404 | Le target_user_id ne correspond à aucun utilisateur existant |
PERMISSION_DENIED | 403 | Permission manquante (impersonate:users ou delegate:tokens) |
SCOPE_EXCEEDS_ORIGINAL | 400 | Les scopes demandés dépassent ceux du token sujet original |
DPoP — Demonstrating Proof of Possession (RFC 9449)
Les tokens DPoP sont cryptographiquement liés au client qui les a obtenus. Contrairement aux tokens Bearer standard, les tokens DPoP ne peuvent pas être utilisés par un attaquant qui les intercepte car les appels API nécessitent une preuve JWT fraîche signée avec la clé privée du client.
Comment Fonctionne DPoP
- Génération des clés : Le client génère une paire de clés à courbe elliptique (EC P-256 ou RSA). La clé privée ne quitte jamais le client.
- Création de la preuve : Pour chaque requête, le client crée un JWT de preuve DPoP signé avec la clé privée, incluant la méthode HTTP, l’URL et un
jtiunique. - Binding du token : Le serveur valide la preuve, extrait le thumbprint JWK et lie le token émis à cette clé publique.
- Appels API : Les appels API suivants nécessitent à la fois le token DPoP et une nouvelle preuve DPoP fraîche pour cette requête spécifique.
Structure de la Preuve DPoP
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik...Le JWT de preuve DPoP a la structure suivante :
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"
}| Champ | Description |
|---|---|
htm | Méthode HTTP de la requête (GET, POST, etc.) |
htu | URL complète de la requête sans query string |
iat | Issued At — le décalage d’horloge autorisé est de 30 secondes |
jti | Identifiant unique pour cette preuve spécifique (prévient le replay) |
nonce | Nonce fourni par le serveur (obligatoire quand le serveur l’inclut dans la réponse) |
Token DPoP dans la Réponse
Lors de l’obtention d’un token avec DPoP, la réponse inclut "token_type": "DPoP" au lieu de "Bearer". Le JWT du token d’accès contient un claim cnf.jkt avec le thumbprint JWK :
{
"sub": "usr_abc123",
"cnf": {
"jkt": "0ZcOCORZNYy-DWpqq30jZyJGHTN0d2HglBV3uiguA4I"
}
}Pour utiliser un token DPoP, inclus l’en-tête Authorization: DPoP <token> ainsi qu’un en-tête DPoP: <fresh-proof>.
Gestion du Nonce
Le serveur peut nécessiter un nonce pour prévenir les replays. Inclus le nonce dans les preuves DPoP suivantes :
DPoP-Nonce: eyJ...server-issued-nonce...Ce nonce doit être inclus dans le claim nonce de ton prochain JWT de preuve DPoP. Si tu envoies une preuve sans nonce quand il est requis, tu recevras une erreur use_dpop_nonce avec un nonce frais dans l’en-tête de la réponse.
Codes d’erreur
| Code | HTTP | Description |
|---|---|---|
INVALID_DPOP_PROOF | 401 | La preuve DPoP n’est pas valide (signature invalide, expirée, jti réutilisé) |
DPOP_NONCE_REQUIRED | 401 | Un nonce est requis — voir l’en-tête DPoP-Nonce dans la réponse |
DPOP_JKT_MISMATCH | 401 | La clé publique dans la preuve ne correspond pas au thumbprint dans le token |
DPOP_DISABLED | 400 | DPoP non activé pour cette application |
CIBA — Authentification Backchannel (Client-Initiated Backchannel Authentication)
CIBA permet à un service de lancer une authentification en arrière-plan sur un appareil ou canal séparé (comme une notification push mobile) sans rediriger le navigateur. Utile pour les centres d’appel, l’authentification à distance et les applications sur des appareils séparés.
/api/oauth/backchannel/authorizeRequires: manage:ciba_configLance un flux d’authentification backchannel pour l’utilisateur identifié. Auris envoie une notification d’authentification à l’utilisateur (push, notification in-app, etc.). Le service effectue un polling ou attend un callback pour le token.
Corps de la requête
{
"client_id": "app_abc123",
"client_secret": "app_secret_xyz",
"scope": "openid profile",
"login_hint": "[email protected]",
"binding_message": "Autoriser paiement 50€ à Jane",
"requested_expiry": 300
}| Champ | Obligatoire | Description |
|---|---|---|
client_id | Oui | L’identifiant de l’application |
client_secret | Oui | Le secret de l’application |
scope | Oui | Scopes OAuth à demander |
login_hint | Oui | Email ou ID de l’utilisateur à authentifier |
binding_message | Non | Court message lisible affiché à l’utilisateur pour associer la demande à une action. Maximum 256 caractères. |
requested_expiry | Non | Secondes de validité de la demande. Défaut 300, maximum 600. |
Réponse de succès
{
"ok": true,
"data": {
"auth_req_id": "1c266114-a1be-4252-8ad1-04986c5b9ac9",
"expires_in": 300,
"interval": 5
}
}Modes de Notification
La façon dont ton service reçoit le résultat de l’authentification dépend du mode CIBA configuré pour l’application :
| Mode | Comportement |
|---|---|
poll | Ton service effectue un polling sur l’endpoint token avec auth_req_id |
ping | Auris envoie un callback HTTP à ton application (notification_endpoint) quand l’utilisateur répond ; puis ton service appelle l’endpoint token |
push | Auris envoie le token directement à ton application (notification_endpoint) après la réponse de l’utilisateur |
Polling CIBA
Pour le mode poll, effectue un polling sur l’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"
}Les réponses de polling fonctionnent de la même façon que le Device Flow : AUTHORIZATION_PENDING, SLOW_DOWN, EXPIRED_TOKEN, ACCESS_DENIED, ou un token de succès.
Codes d’erreur
| Code | HTTP | Description |
|---|---|---|
CIBA_DISABLED | 400 | CIBA non activé pour cette application |
USER_NOT_FOUND | 404 | L’utilisateur spécifié dans login_hint n’existe pas |
NOTIFICATION_FAILED | 502 | Auris n’a pas pu envoyer la notification à l’appareil de l’utilisateur |
BINDING_MESSAGE_TOO_LONG | 400 | Le binding_message dépasse 256 caractères |
Évaluation du Risque et MFA Adaptatif
Auris évalue le risque de chaque événement d’authentification en temps réel. Sur la base du score de risque, il peut autoriser la connexion, demander une étape MFA supplémentaire, ou bloquer complètement la tentative d’authentification.
Facteurs de Risque
Chaque facteur contribue à hauteur de 20% au score de risque global :
| Facteur | Description |
|---|---|
| Réputation IP | Vérifie si l’IP source est une IP malveillante connue, un VPN, un proxy ou un réseau datacenter |
| Confiance Appareil | Détermine si l’empreinte de l’appareil a déjà été vue pour cet utilisateur |
| Anomalie Géographique | Détecte les voyages impossibles et les localisations géographiques inhabituelles |
| Comportement | Analyse les patterns de connexion comme l’heure inhabituelle et les tentatives d’accès échouées répétées |
| Sensibilité de l’Action | La sensibilité de l’action demandée (opération normale vs. opération critique de sécurité) |
Niveaux de Risque
| Niveau | Score | Action par défaut |
|---|---|---|
LOW | 0–30 | Autoriser la connexion |
MEDIUM | 31–60 | Demander MFA |
HIGH | 61–80 | Demander MFA fort (clé matérielle ou biométrie) |
CRITICAL | 81–100 | Bloquer la connexion |
Claims JWT ACR et AMR
Les tokens Auris incluent des claims OIDC standard qui décrivent comment l’utilisateur s’est authentifié :
Claim acr (Authentication Context Class Reference)
| Valeur | Description |
|---|---|
urn:auris:acr:pwd | Authentification par mot de passe uniquement |
urn:auris:acr:mfa | Authentification multi-facteur complétée |
urn:auris:acr:strong | MFA fort avec clé matérielle ou biométrie |
Claim amr (Authentication Methods References)
Tableau des méthodes utilisées lors de l’authentification : pwd, otp, sms, webauthn, social, magic_link, sso
{
"sub": "usr_abc123",
"acr": "urn:auris:acr:mfa",
"amr": ["pwd", "otp"]
}API d’Évaluation du Risque
/api/auth/risk/assessmentsRequires: view:risk_assessmentsListe les évaluations de risque d’authentification avec filtres. Chaque entrée inclut le score de risque, les facteurs contributeurs et l’action prise par le moteur de risque.
Paramètres de requête
| Paramètre | Type | Description |
|---|---|---|
page | number | Numéro de page (défaut : 1) |
limit | number | Résultats par page (défaut : 20, max : 100) |
userId | string | Filtrer par ID utilisateur spécifique |
level | string | Filtrer par niveau de risque : LOW, MEDIUM, HIGH, CRITICAL |
dateFrom | string | Date de début ISO 8601 |
dateTo | string | Date de fin ISO 8601 |
Exemple de réponse
{
"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": "FR",
"city": "Paris",
"createdAt": "2025-02-18T14:30:00Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 142,
"pages": 8
}
}Règles de Risque Personnalisées
Tu peux étendre le moteur d’évaluation du risque avec des règles custom qui remplacent ou augmentent le comportement par défaut.
/api/auth/risk/rulesRequires: manage:risk_rulesListe toutes les règles de risque custom configurées pour le tenant.
/api/auth/risk/rulesRequires: manage:risk_rulesCrée une nouvelle règle de risque custom. Les règles sont évaluées à chaque événement d’authentification.
Corps de la requête
{
"name": "Bloquer les accès depuis des proxies connus",
"condition": {
"field": "ipReputation.isProxy",
"operator": "equals",
"value": true
},
"action": "block",
"scoreModifier": 50,
"isActive": true
}| Champ | Obligatoire | Description |
|---|---|---|
name | Oui | Nom descriptif pour la règle |
condition | Oui | La condition à évaluer (voir tableau des champs ci-dessous) |
action | Oui | Action : allow, step_up_mfa, block, log |
scoreModifier | Non | Ajoute cette valeur (0–100) au score de risque quand la condition est vraie |
isActive | Oui | Si la règle est active |
Champs de condition disponibles
| Champ | Type | Description |
|---|---|---|
ipReputation.isVpn | boolean | L’IP est un VPN |
ipReputation.isProxy | boolean | L’IP est un proxy |
ipReputation.isDatacenter | boolean | L’IP est dans une plage datacenter |
deviceTrust.isNewDevice | boolean | L’appareil n’a jamais été vu auparavant pour cet utilisateur |
geoAnomaly.isNewCountry | boolean | Connexion depuis un pays jamais vu auparavant pour cet utilisateur |
geoAnomaly.distance | number | Distance en km depuis la précédente localisation de connexion |
behavior.unusualTime | boolean | Connexion à une heure inhabituelle pour cet utilisateur |
behavior.failedAttempts | number | Nombre de tentatives récentes échouées |
Opérateurs disponibles
equals, not_equals, greater_than, less_than, contains, in
/api/auth/risk/rules/[id]Requires: manage:risk_rulesMet à jour une règle de risque existante. Accepte les mêmes champs que la création. Tu peux mettre à jour partiellement (seuls les champs spécifiés sont modifiés).
/api/auth/risk/rules/[id]Requires: manage:risk_rulesSupprime définitivement une règle de risque custom. La suppression est irréversible.
Référence des Permissions
| Permission | Description |
|---|---|
manage:device_codes | Active et utilise le Device Authorization Flow |
impersonate:users | Exécute Token Exchange avec exchange_type: "impersonation" |
delegate:tokens | Exécute Token Exchange avec exchange_type: "delegation" |
manage:dpop_config | Configure les paramètres DPoP pour les applications |
manage:ciba_config | Configure et lance les demandes d’authentification CIBA |
view:risk_assessments | Lit les logs et données d’évaluation du risque |
manage:risk_rules | Crée, met à jour et supprime les règles de risque custom |
manage:advanced_oauth | Configuration OAuth 2.0 avancé complète |
Corrélés
- Concept DPoP — Comment fonctionne le binding de clé DPoP
- Concept Device Flow — Device Authorization Flow expliqué
- Concept CIBA — Authentification backchannel
- Concept Token Exchange — Impersonation et délégation
- Utilisation de DPoP — Implémentation des tokens DPoP
- Device Flow — Guide du Device Flow
- CIBA — Configuration de l’authentification backchannel
- Token Exchange — Guide de l’échange de tokens
- OAuth Avancé Admin — Configuration depuis la Console