Le guide

Quel flow choisir ?

Un « flow » (ou « grant ») est la façon dont une application obtient ses jetons. Il y en a plusieurs parce que les applications sont très différentes : un site web, une application mobile, un téléviseur, un service sans utilisateur… n’ont pas les mêmes contraintes ni les mêmes secrets à protéger.

Voir aussi : les flows en diagrammes de séquence · les fonctions avancées expliquées (PAR, JAR, JARM, DPoP, CIBA) · la frise de l’évolution d’OAuth et d’OpenID Connect

En deux questions

  1. Y a-t-il une personne qui se connecte ? Non, c’est un service qui parle à un autre service → Client Credentials.
  2. Oui. Où tourne l’application ?
    • Site web, application mobile, application monopage (SPA), application de bureau, avec un navigateur → Authorization Code + PKCE. C’est la réponse dans 95 % des cas.
    • Appareil sans navigateur ni clavier (télévision, console, objet connecté, outil en ligne de commande) → Device Code.

Tout le reste existe pour des raisons historiques ou des besoins précis. Refresh Token n’est pas un flow de connexion : c’est un complément pour garder la session.

Pourquoi tant de flows ?

OAuth 2.0 (2012) a dû servir à la fois des serveurs capables de garder un secret et des applications dans un navigateur qui ne le peuvent pas. D’où l’implicit pour les SPA, le password pour les applications « de confiance », et le code pour les serveurs. Avec les années, on a constaté que les jetons dans l’URL fuyaient (implicit) et que donner son mot de passe à l’application annulait tout l’intérêt (password). OAuth 2.1 et les recommandations de sécurité actuelles ont donc tout ramené au code + PKCE, en gardant client credentials et device pour leurs cas propres. OIDC a ajouté le flow hybride pour obtenir l’identité tout de suite.

Les flows, un par un

Authorization Code + PKCELe flow standard pour toute personne qui se connecte.Recommandé

À utiliser quand : une personne se connecte à un site web (avec ou sans serveur), une SPA, une application mobile ou de bureau. Avec un serveur capable de garder un secret, ajoutez le client_secret ; sans (SPA, mobile), PKCE suffit.

Pourquoi il existe : le navigateur ne reçoit qu’un code à usage unique et de courte durée ; les jetons, eux, passent directement du serveur de l’application à l’OP (« canal arrière »). PKCE lie le code à celui qui l’a demandé, ce qui empêche qu’un code intercepté serve à quelqu’un d’autre.

Les pièges : oublier PKCE (aujourd’hui exigé même pour les clients confidentiels), ne pas vérifier state et nonce, accepter des redirect_uri trop larges, jetons dans localStorage pour une SPA.

Déroulé :

  1. L’application génère code_verifier (secret aléatoire), state, nonce, et calcule code_challenge = SHA-256(code_verifier).
  2. Elle envoie la personne à /authorize?response_type=code&code_challenge=…&state=…&nonce=….
  3. L’OP authentifie la personne, puis la renvoie sur redirect_uri?code=…&state=….
  4. L’application appelle /token avec le code et le code_verifier (et son secret si elle en a un).
  5. Elle reçoit ID token, access token (et refresh token), puis vérifie signature, iss, aud, nonce.
Hybride (code id_token, code token…)Code plus ID token directement dans la redirection.Cas précis

À utiliser quand : l’application a besoin de l’identité immédiatement (avant l’échange du code), par exemple pour une validation de session côté serveur ou parce qu’une ancienne bibliothèque (ASP.NET, Java EE) le configure par défaut.

Pourquoi il existe : OIDC a voulu permettre de lire l’identité tout de suite tout en gardant le code pour obtenir les jetons de manière sûre. Le c_hash et at_hash de l’ID token lient le code et l’access token à cette identité.

Les pièges : jetons dans le fragment de l’URL (visibles de l’historique et des scripts), c_hash/at_hash non vérifiés, et un nonce obligatoire oublié. Préférez le code seul si rien ne vous y oblige.

Déroulé :

  1. /authorize?response_type=code id_token&nonce=… (ou code token, code id_token token).
  2. L’OP renvoie #code=…&id_token=…&state=… dans le fragment (response_mode=fragment par défaut) ou en POST (form_post).
  3. L’application vérifie l’ID token et son c_hash.
  4. Elle échange le code contre les autres jetons, comme dans le flow code.
Implicit (id_token, id_token token)Les jetons arrivent directement dans l’URL.Déconseillé

À utiliser quand : presque jamais pour du neuf. Vous le rencontrez dans de vieilles SPA, ou pour vérifier qu’une application l’interdit bien.

Pourquoi il existe : avant que les navigateurs gèrent les appels croisés (CORS) et PKCE, une SPA ne pouvait pas appeler /token ; on lui donnait donc les jetons directement.

Les pièges : le jeton circule dans l’URL : historique, journaux de proxy, en-tête Referer, extensions. Aucun refresh token, aucune liaison à l’appelant. Retiré d’OAuth 2.1.

Déroulé :

  1. /authorize?response_type=id_token token&nonce=….
  2. L’OP renvoie #id_token=…&access_token=…&state=….
  3. Un script de la page lit le fragment et vérifie le jeton.
Client CredentialsPas de personne : le service s’authentifie lui-même.Machine à machine

À utiliser quand : un service, un traitement planifié ou un démon appelle une API en son nom propre : synchronisation, tâche de nuit, microservices entre eux.

Pourquoi il existe : beaucoup d’appels d’API n’ont aucune personne derrière. Le client prouve son identité (secret, ou mieux : assertion signée) et reçoit un access token limité à ses scopes.

Les pièges : pas d’ID token ni de refresh token (c’est normal). Ne mettez jamais ce secret dans une application distribuée (mobile, SPA). Donnez le strict minimum de scopes et faites tourner le secret.

Déroulé :

  1. POST /token avec grant_type=client_credentials, scope=… et l’authentification du client (secret Basic ou dans le corps).
  2. L’OP répond avec un access token.
  3. Le service l’envoie à l’API : Authorization: Bearer ….
Refresh TokenRenouveler un access token sans redemander la personne.Complément

À utiliser quand : vous voulez des access tokens de courte durée (quelques minutes) tout en gardant la personne connectée longtemps. Se demande avec le scope offline_access.

Pourquoi il existe : plus un jeton vit longtemps, plus son vol est grave. Le refresh token reste côté application, loin des API, et ne sert qu’à renouveler.

Les pièges : refresh token volé = accès prolongé : stockage sûr, rotation (un nouveau à chaque usage, l’ancien devient invalide) et détection de réutilisation.

Déroulé :

  1. POST /token avec grant_type=refresh_token&refresh_token=….
  2. L’OP renvoie un nouvel access token (et souvent un nouveau refresh token, l’ancien étant révoqué).
Device Code (RFC 8628)Se connecter sur un autre appareil.Appareils sans navigateur

À utiliser quand : télévision, console, objet connecté, imprimante, outil en ligne de commande : l’appareil n’a pas de navigateur ou de clavier pratique.

Pourquoi il existe : saisir un mot de passe avec une télécommande est pénible et risqué. On affiche un court code ; la personne le saisit sur son téléphone ou son ordinateur, où elle s’authentifie normalement.

Les pièges : code de courte durée et à usage unique, pas de sondage trop rapide (slow_down), et limitation des essais pour éviter qu’on devine un code. Hameçonnage possible : affichez bien ce que la personne autorise.

Déroulé :

  1. L’appareil appelle /device_authorization et reçoit device_code, user_code et l’adresse de vérification.
  2. Il affiche « allez sur … et saisissez ABCD-EFGH ».
  3. La personne s’authentifie et saisit le code sur son téléphone.
  4. Pendant ce temps l’appareil interroge /token avec le device_code. D’abord authorization_pending, puis les jetons.
Resource Owner Password CredentialsL’application reçoit directement le mot de passe.Déconseillé

À utiliser quand : à éviter. Parfois toléré pour une migration depuis un ancien système ou des tests automatisés dans un environnement contrôlé.

Pourquoi il existe : une transition pour les applications qui collectaient déjà des mots de passe, sans changer leur interface.

Les pièges : l’application voit le mot de passe : exactement ce que l’OIDC cherche à éviter. Pas d’authentification multifacteur, pas de SSO, hameçonnage facilité. Retiré d’OAuth 2.1.

Déroulé :

  1. POST /token avec grant_type=password&username=…&password=….
  2. L’OP répond avec les jetons, ou refuse si un second facteur est exigé.

Aussi dans la nature

  • private_key_jwt et JWT Bearer (RFC 7523) : un service prouve son identité avec une assertion signée plutôt qu’un secret partagé. Idéal pour les échanges entre systèmes. Dans ID-Kit côté fournisseur de test ; pas encore côté application de test.
  • Token Exchange (RFC 8693) : échanger un jeton contre un autre, pour une API qui appelle une autre API au nom de la personne. Dans ID-Kit.
  • PAR et JAR (RFC 9126 et 9101) : la demande d’autorisation est déposée de serveur à serveur, ou signée. Dans ID-Kit : fournisseur de test (PAR et JAR) et application de test (PAR).
  • CIBA : l’authentification se fait sur un autre canal, à l’initiative du serveur (centre d’appels, banque). Dans ID-Kit (fournisseur de test, mode poll).

Tous les détails en images : diagrammes de séquence.

Les protections qui vont avec

  • PKCE : prouve que celui qui échange le code est celui qui l’a demandé.
  • state : lie la réponse à la demande, contre le CSRF.
  • nonce : lie l’ID token à la session de l’application, contre le rejeu.
  • redirect_uri exacte : l’OP n’envoie le code qu’à une adresse enregistrée, caractère pour caractère.

Tester chaque flow. Le fournisseur de test d’ID-Kit sait jouer tous ces flows, avec des erreurs simulées ; l’application de test les déroule contre votre vrai fournisseur.