OpenID Connect · OAuth 2.0

Les fonctions avancées, expliquées simplement

Ces mécanismes renforcent la sécurité du flux de base. Chacun répond à une faille précise : on commence par le problème, puis la solution.

Le fil rouge

Le flux de base envoie des informations dans le navigateur, où tout le monde peut y toucher. Les fonctions avancées fixent ça à chaque étape : PAR et JAR protègent la demande, private_key_jwt protège l’identité de l’application, JARM protège la réponse, DPoP protège le jeton une fois émis, et CIBA traite le cas où il n’y a pas de navigateur. Viennent s’y ajouter resource (à quelle API), RAR (quelle opération précise), acr (quel niveau d’authentification) et l’enregistrement dynamique des clients.

private_key_jwt · PAR · JAR · JARM · DPoP · CIBA · Resource indicators · RAR · acr et step-up · Enregistrement dynamique de clients · Pairwise et userinfo signé

private_key_jwt

RFC 7523 / OIDC Core 9

Prouver qui vous êtes avec une signature plutôt qu’avec un mot de passe partagé.

Le problème

Un client confidentiel s’authentifie normalement avec un « client_secret », un mot de passe que le client et le serveur connaissent tous les deux. S’il fuit d’un côté, l’autre n’a aucun moyen de le savoir, et le secret circule dans des fichiers de configuration.

Comment ça marche

Le client garde une clé privée qui ne quitte jamais chez lui. À chaque appel, il fabrique une petite « attestation » signée (un JWT) qui dit « je suis tel client, je m’adresse à ce serveur, et ceci n’est valable que quelques minutes ». Le serveur ne possède que la clé publique : il vérifie la signature, c’est tout.

En image

Au lieu d’un mot de passe que le gardien connaît, vous signez chaque entrée avec votre stylo personnel ; le gardien a seulement un spécimen de votre signature.

Quand l’utiliser

Banques, administrations, tout environnement qui interdit les secrets partagés. Obligatoire dans plusieurs profils de sécurité (FAPI).

Les pièges

Attestation rejouée (d’où l’identifiant « jti » à usage unique), audience incorrecte, durée trop longue, mauvaise clé.

Dans ID-Kit

Créez un client de type « Confidentiel par clé (private_key_jwt) » dans votre fournisseur de test, collez-y votre certificat ou votre JWKS public, puis appelez /token avec client_assertion. ID-Kit vous dit précisément pourquoi une attestation est refusée.

PAR : demande d’autorisation poussée

RFC 9126

Déposer sa demande de connexion directement chez le serveur, sans la faire passer par le navigateur.

Le problème

Normalement, la demande (qui je suis, ce que je veux, où revenir) est écrite dans l’adresse de la page et traverse le navigateur : l’utilisateur ou un programme malveillant peut la lire ou la modifier, et les adresses très longues posent problème.

Comment ça marche

L’application envoie d’abord toute sa demande au serveur, de serveur à serveur, en s’authentifiant. Le serveur répond par un simple « ticket » (request_uri) valable une minute. L’application envoie alors le navigateur vers le serveur avec seulement ce ticket. Le ticket ne sert qu’une fois.

En image

Au lieu de dicter votre commande à voix haute dans la salle, vous la remettez en cuisine et vous ne montrez à la salle qu’un numéro de ticket.

Quand l’utiliser

Dès qu’on veut empêcher qu’un paramètre soit falsifié (montant, scopes, redirect_uri) : banque, santé, paiement. Exigé par FAPI.

Les pièges

Ticket expiré (60 s), déjà utilisé, ou présenté par un autre client que celui qui l’a déposé.

Dans ID-Kit

Fournisseur de test : appelez /par. Côté application de test, choisissez le flux « code_par ». Le réglage « Exiger PAR » du fournisseur refuse les demandes classiques.

JAR : demande d’autorisation signée

RFC 9101

Signer la demande de connexion pour que personne ne puisse la modifier en route.

Le problème

Même avec les paramètres dans l’adresse, rien ne prouve qu’ils viennent bien de l’application et qu’ils n’ont pas été changés.

Comment ça marche

Les paramètres sont rassemblés dans un JWT signé avec la clé du client (paramètre « request »). Le serveur vérifie la signature, l’émetteur, l’audience et la date. Les paramètres du JWT remplacent ceux de l’adresse.

En image

Une lettre sous enveloppe scellée à la cire : si le sceau est brisé, le serveur le voit.

Quand l’utiliser

Avec PAR dans les profils de sécurité élevés ; seul, quand on n’a pas de canal serveur à serveur.

Les pièges

Clé publique du client non enregistrée, « aud » qui n’est pas l’émetteur du serveur, JWT expiré, client_id différent.

Dans ID-Kit

Enregistrez la clé publique du client puis envoyez votre JWT dans « request » ou dans /par. Les mauvaises signatures et audiences sont expliquées.

JARM : réponse d’autorisation signée

FAPI JARM

Le serveur signe aussi sa réponse : l’application sait qu’elle vient bien de lui et n’a pas été modifiée.

Le problème

Quand le serveur renvoie l’utilisateur vers l’application avec « code=… » dans l’adresse, n’importe qui dans le navigateur peut y toucher. Cela ouvre la voie à des attaques où un autre serveur se fait passer pour le bon (« mix-up »).

Comment ça marche

Au lieu de plusieurs paramètres en clair, le serveur renvoie un seul paramètre « response » : un JWT signé qui contient code, state, l’émetteur (iss) et l’audience (aud). L’application vérifie la signature, puis lit le code à l’intérieur. Quatre variantes : jwt, query.jwt, fragment.jwt, form_post.jwt (où le JWT est placé).

En image

La réponse arrive dans une enveloppe plombée plutôt que sur une carte postale.

Quand l’utiliser

Profil FAPI 2.0 et secteurs réglementés. Utile aussi pour détecter les attaques de mélange entre serveurs.

Les pièges

Oublier de vérifier la signature, ou lire des paramètres en clair à côté du JWT. query.jwt est interdit quand des jetons reviennent par le navigateur.

Dans ID-Kit

Ajoutez response_mode=jwt (ou une variante) à votre demande d’autorisation sur le fournisseur de test : même un refus ou une erreur est signé.

DPoP : jeton lié à une clé

RFC 9449

Un jeton volé ne sert à rien sans la clé de l’application qui l’a demandé.

Le problème

Un jeton « Bearer » (porteur) fonctionne comme de l’argent liquide : celui qui le possède peut l’utiliser, même s’il l’a volé dans un journal, une extension de navigateur ou une API compromise.

Comment ça marche

L’application fabrique une paire de clés. À chaque appel, elle joint une « preuve » courte signée avec sa clé privée, qui dit « voici la méthode et l’adresse que j’appelle, à cet instant ». Le serveur lie le jeton à l’empreinte de la clé (cnf.jkt). L’API vérifie que la preuve a été signée par la même clé et qu’elle porte l’empreinte du jeton (ath). Un voleur qui a le jeton mais pas la clé privée est bloqué.

En image

Une carte bancaire avec code PIN, plutôt que des billets : la carte seule ne suffit pas.

Quand l’utiliser

Applications mobiles et pages web (SPA) où les jetons sont exposés, API sensibles, profils FAPI 2.0.

Les pièges

Preuve rejouée (jti à usage unique), mauvaise méthode ou adresse (htm, htu), horloge décalée (iat ±2 min), jeton présenté avec « Bearer » au lieu de « DPoP », ath manquant sur l’API.

Dans ID-Kit

Envoyez un en-tête DPoP à /token du fournisseur de test : le jeton devient token_type DPoP avec cnf.jkt. Sur /userinfo, il faut « Authorization: DPoP » plus une preuve avec ath, sinon un message explique ce qui manque.

CIBA : authentification sur un autre appareil

OpenID CIBA Core

Une application demande au serveur d’authentifier quelqu’un sur son téléphone, sans navigateur ni redirection.

Le problème

Dans un guichet, un centre d’appels, un terminal de paiement ou un assistant vocal, la personne n’est pas devant un navigateur qui peut se rediriger.

Comment ça marche

L’application dit au serveur « authentifie Alice » (login_hint), avec éventuellement un message à afficher (« Autoriser le paiement de 25 € ? ») et reçoit un auth_req_id. Le serveur sollicite Alice sur son téléphone. Pendant ce temps, l’application interroge /token (« poll ») : « authorization_pending » tant qu’Alice n’a pas répondu, puis les jetons si elle accepte, ou « access_denied » si elle refuse.

En image

Le vendeur appelle votre banque pour dire « mon client est là », et c’est votre banque qui vous envoie une notification pour confirmer.

Quand l’utiliser

Validation de paiement ou d’opération sensible, centres d’appels, bornes, téléphonie. Le message de liaison (binding_message) apparaît sur les deux écrans pour vérifier qu’on valide bien la bonne opération.

Les pièges

Interroger trop vite (slow_down), laisser expirer la demande, oublier que le login_hint doit désigner un utilisateur connu du serveur.

Dans ID-Kit

Activez le flux CIBA sur un client du fournisseur de test, appelez /bc-authorize. La réponse contient un lien « idkit_approval_url » : c’est la page du « téléphone », où vous approuvez ou refusez, puis vous récupérez les jetons avec /token. ID-Kit ne gère que le mode poll.

Resource indicators : à quelle API le jeton est destiné

RFC 8707

Dire à quelle API on veut parler, pour que le jeton ne marche que là.

Le problème

Un jeton d’accès valable pour « n’importe quelle API » est dangereux : si l’API de facturation est compromise, elle peut rejouer le jeton contre l’API des salaires.

Comment ça marche

L’application ajoute « resource=https://api.exemple.fr/factures » à sa demande (autorisation ou jeton). Le fournisseur place cette adresse dans l’audience (aud) du jeton. L’API vérifie que aud est bien elle, et refuse sinon.

En image

Un billet de train nominatif pour une ligne précise, plutôt qu’un ticket valable partout.

Quand l’utiliser

Dès qu’il y a plusieurs API derrière un même fournisseur, et pour les jetons sensibles.

Les pièges

API qui ne vérifie pas aud ; resource avec un fragment (#) ou qui n’est pas une adresse absolue (invalid_target).

Dans ID-Kit

Ajoutez resource à /authorize ou /token du fournisseur de test : l’audience du jeton JWT et de l’introspection change. La ressource est mémorisée dans le code et conservée au rafraîchissement.

RAR : autorisations détaillées

RFC 9396

Demander un droit précis (« payer 25 € à X ») plutôt qu’un large scope (« payer »).

Le problème

Un scope comme « payments » est trop vague : l’utilisateur ne sait pas ce qu’il approuve, et le jeton permet bien plus que l’opération prévue.

Comment ça marche

L’application envoie authorization_details : une liste JSON d’objets avec un « type » (par exemple payment_initiation) et les détails de l’opération (montant, bénéficiaire). Le fournisseur les affiche, les recopie dans le jeton et dans la réponse, et l’API les lit.

En image

Un chèque rempli (montant, destinataire) plutôt qu’un chèque en blanc.

Quand l’utiliser

Paiement, santé, délégations fines. Obligatoire dans certains profils bancaires.

Les pièges

JSON invalide ou sans « type » (invalid_authorization_details) ; API qui ignore le contenu du jeton.

Dans ID-Kit

Envoyez authorization_details sur /authorize ou /token : ID-Kit le valide et le retrouve dans le jeton, la réponse /token et l’introspection.

acr et step-up : niveau d’authentification

OIDC Core, RFC 9470

Savoir avec quelle force la personne s’est authentifiée, et en exiger davantage si besoin.

Le problème

Se connecter avec un mot de passe ne suffit pas pour virer 10 000 €. L’application doit pouvoir dire « je veux une authentification forte ».

Comment ça marche

L’application demande acr_values (par exemple le niveau « mfa »). Le fournisseur renvoie dans l’ID token la valeur acr obtenue et la liste amr des méthodes utilisées (mot de passe, code à usage unique…). Une API peut refuser un jeton de niveau trop faible et demander un « step-up » : on repart faire une authentification plus forte.

En image

À la banque, on vous laisse consulter votre compte avec votre carte, mais pour un virement important on vous demande une pièce d’identité en plus.

Quand l’utiliser

Opérations sensibles, conformité (authentification forte).

Les pièges

Considérer acr_values comme une obligation alors que c’est une demande (« voluntary ») ; ne pas vérifier acr reçu.

Dans ID-Kit

Ajoutez acr_values=urn:idkit:acr:mfa : l’ID token contient acr et amr [pwd, otp], et l’introspection renvoie acr et auth_time. Sans demande, le niveau est « pwd ».

Enregistrement dynamique de clients

RFC 7591

Une application s’enregistre toute seule chez le fournisseur, sans passer par un administrateur.

Le problème

Créer les clients à la main ne passe pas à l’échelle : outils, extensions, serveurs MCP, applications mobiles installées par des milliers de personnes.

Comment ça marche

L’application envoie un POST JSON à /register (nom, adresses de retour, flux voulus, méthode d’authentification). Le fournisseur crée le client et renvoie client_id et, si besoin, client_secret.

En image

Un guichet automatique d’inscription au lieu d’un rendez-vous avec l’accueil.

Quand l’utiliser

Écosystèmes ouverts, outils qui se branchent sur des fournisseurs inconnus.

Les pièges

Redirections non sûres (http hors localhost), grants incohérents avec la méthode d’authentification, absence de limite.

Dans ID-Kit

Activez « Autoriser l’enregistrement dynamique » dans les réglages du fournisseur de test, puis POST sur /register. La limite est de 25 clients.

Pairwise et userinfo signé

OIDC Core 8.1 et 5.3.2

Un identifiant différent par application, et des informations de profil signées.

Le problème

Si toutes les applications voient le même identifiant (sub) pour une personne, elles peuvent comparer leurs bases et la suivre d’un service à l’autre.

Comment ça marche

En mode pairwise, le fournisseur calcule un sub différent pour chaque domaine d’application : le même utilisateur apparaît sous deux identifiants différents chez deux applications. Séparément, /userinfo peut répondre par un JWT signé au lieu d’un simple JSON, pour que l’application puisse prouver l’origine des informations.

En image

Un pseudonyme différent par site au lieu d’un numéro de sécurité sociale partout.

Quand l’utiliser

Respect de la vie privée (administrations, santé, éducation) ; environnements où les informations de profil doivent être signées.

Les pièges

Associer des comptes entre applications avec le sub (impossible en pairwise) ; oublier que sub dans userinfo doit être identique à celui de l’ID token.

Dans ID-Kit

Deux réglages du fournisseur de test : « Identifiant propre à chaque application (pairwise) » et « userinfo en JWT signé ».

Voir aussi : les diagrammes de séquence · quel flow choisir ? · la frise