OAuth 2.1 et OIDC : le guide pour enfin tout comprendre
OAuth est un protocole de délégation, pas d'authentification. La moitié des bugs d'identité naissent de cette confusion. Voici le modèle mental, les flux et la checklist de validation qui tiennent la route.
Par Innovation T Team
OAuth est un protocole de délégation, pas un protocole d'authentification. Cette seule confusion est à l'origine de la moitié des bugs d'identité que nous relevons en audit de sécurité. Si vos équipes livrent des boutons de connexion, des tokens d'API ou des services machine à machine, les dix prochaines minutes vous éviteront un incident.
Désapprendre le mauvais modèle mental
OAuth 2.x répond à une question, et une seule : cette application a-t-elle le droit d'appeler cette API, éventuellement pour le compte d'un utilisateur. Il ne dit rien de fiable sur l'identité de cet utilisateur. OpenID Connect (OIDC) est la couche d'identité greffée par-dessus : elle ajoute un ID token, un endpoint UserInfo, et des règles strictes pour qu'un client puisse établir qu'un événement d'authentification a réellement eu lieu.
La distinction n'a rien d'académique. Si votre backend traduit « j'ai reçu un access token » par « cet utilisateur est authentifié », n'importe quelle application ayant légitimement obtenu un token pour cet utilisateur peut le rejouer contre votre API et usurper son identité. Ce problème de rejeu d'access token est très exactement la raison d'être d'OIDC. Délégation et authentification sont deux affirmations différentes, qui exigent des tokens différents.
Gardez cette phrase affichée au mur : OAuth dit ce qu'une application a le droit de faire, OIDC dit qui est l'utilisateur.
Ce que change réellement OAuth 2.1
OAuth 2.1 est encore un draft IETF, mais considérez-le comme votre référence. C'est OAuth 2.0 augmenté de dix ans de leçons de sécurité, dont la plupart avaient déjà été formalisées dans la RFC 9700, le Best Current Practice de sécurité OAuth. Viser 2.1 aujourd'hui, c'est simplement faire du 2.0 correctement.
Les changements concrets :
- Le grant implicite est mort. Les tokens livrés dans les fragments d'URL fuyaient via l'historique du navigateur, les en-têtes referrer et les proxys de journalisation. Il n'y avait aucun moyen de corriger cela, donc il a été supprimé.
- Le grant « resource owner password » est mort. Tout flux qui apprend aux utilisateurs à saisir leur mot de passe dans une application tierce est un programme d'entraînement au phishing.
- PKCE devient obligatoire pour chaque flux authorization code, clients confidentiels compris. Il neutralise l'interception du code d'autorisation et offre une protection CSRF en prime.
- Les redirect URI doivent correspondre exactement. Pas de wildcard, pas de correspondance par préfixe, pas de « tout ce qui est sous ce sous-domaine ».
- Les refresh tokens des clients publics doivent être à usage unique (rotation) ou liés à l'émetteur (sender constrained).
- Les bearer tokens dans les chaînes de requête sont bannis. Ils finissent dans les logs d'accès pour toujours.
Si votre fournisseur d'identité ou votre propre implémentation enfreint l'un de ces points, voilà votre backlog de remédiation, dans l'ordre de priorité.
Les pièces du puzzle, précisément
Quatre rôles :
- Resource owner : l'humain propriétaire des données.
- Client : l'application qui demande l'accès (SPA, application mobile, service backend).
- Authorization server (AS) : émet les tokens après avoir authentifié l'utilisateur et enregistré son consentement. Keycloak, Auth0, Entra ID, Cognito, Zitadel.
- Resource server (RS) : votre API, qui accepte et valide les access tokens.
Trois tokens, aux missions très différentes :
- Access token : un identifiant destiné au resource server. Durée de vie courte. Le client doit le traiter comme une chaîne opaque, même quand il se trouve être un JWT.
- Refresh token : un identifiant longue durée que le client échange contre de nouveaux access tokens sans solliciter l'utilisateur. La chose la plus précieuse qu'un attaquant puisse voler.
- ID token (OIDC uniquement) : un JWT adressé au client, et à aucune API. Il atteste que « cet utilisateur s'est authentifié à ce moment, par cette méthode ». Son audience est votre client_id.
Deux règles éliminent des classes entières de bugs :
- Un ID token ne franchit jamais une frontière d'API. Il est consommé par le client, et son travail s'arrête là.
- Un client ne prend jamais de décision en analysant un access token. Le contenu du token est un contrat entre l'AS et le RS.
Les flux qui comptent en 2026
Il vous en faut quatre. Tout le reste relève du legacy.
Authorization code avec PKCE
Le choix par défaut pour tout ce qui est interactif : applications web, SPA, mobile. Le client génère un secret aléatoire (le verifier), envoie son empreinte SHA-256 (le challenge) avec la requête d'autorisation, puis prouve qu'il détient le verifier au moment d'échanger le code. Un attaquant qui intercepte le code ne peut pas l'utiliser.
const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
const digest = await crypto.subtle.digest(
"SHA-256", new TextEncoder().encode(verifier)
);
const challenge = base64url(new Uint8Array(digest));
La requête d'autorisation doit toujours porter response_type=code, un code_challenge avec code_challenge_method=S256, une valeur state que vous vérifiez au retour, et, pour OIDC, scope=openid accompagné d'un nonce que vous contrôlez dans l'ID token. Omettre state ou nonce au motif que « PKCE s'en charge » est un raccourci fréquent. PKCE en couvre l'essentiel. La défense en profondeur vous coûte deux chaînes aléatoires.
Client credentials
Machine à machine, sans utilisateur : un service de facturation qui appelle une API de devis, un cron qui extrait des rapports. Le client s'authentifie avec ses propres identifiants et obtient un token à son nom. Deux disciplines comptent ici : demander un token pour une audience précise, jamais un token universel, et conserver le secret client dans un coffre-fort avec rotation, pas dans un fichier d'environnement committé « provisoirement ».
Device authorization grant
Pour les appareils sans clavier digne de ce nom : téléviseurs connectés, CLI, bornes interactives. L'appareil affiche un code court, l'utilisateur valide sur son téléphone, l'appareil interroge le serveur jusqu'à recevoir le token. Si vous avez déjà saisi un code sur github.com/login/device, vous l'avez utilisé.
Token exchange
RFC 8693, pour les chaînes de services. Le service A reçoit le token d'un utilisateur et doit appeler le service B pour son compte. L'anti-pattern consiste à propager le token d'origine à travers cinq services, chacun acceptant un token qui ne lui était pas destiné. Le token exchange permet à A d'échanger le token entrant contre un nouveau, restreint à B, avec la chaîne de délégation consignée dans le claim act. D'expérience, c'est la brique qui manque à la plupart des parcs de microservices, et c'est pourquoi un seul token volé ouvre si souvent une plateforme entière.
Validez vos tokens sérieusement
Les access tokens existent en deux formats. Les tokens opaques exigent un appel à l'endpoint d'introspection (RFC 7662) : plus de latence, révocation immédiate. Les JWT se valident localement grâce aux clés publiées par l'AS (JWKS) : rapide, mais la révocation ne prend effet qu'à l'expiration. Le compromis standard : des access tokens JWT d'une durée de vie de 5 à 15 minutes avec rotation des refresh tokens, et l'introspection réservée aux opérations à fort enjeu.
La validation locale des JWT, c'est là que les audits font mal. Déroulez cette checklist sur chaque resource server, à chaque fois :
- Récupérez les clés de signature via l'endpoint JWKS, sélectionnez par
kid, et mettez en cache avec un TTL raisonnable. Ne codez jamais les clés en dur. - Verrouillez une liste blanche d'algorithmes. Attendez
RS256ouES256, rejetez tout le reste. Cette seule ligne éliminealg: noneet la classique attaque par confusion de clé RS256 vers HS256. - Vérifiez
isscontre l'URL exacte de l'émetteur. Https, et gare aux surprises de slash final. - Vérifiez que
audcontient l'identifiant de votre API. Un token valide pour l'API d'un autre n'est pas un token valide pour la vôtre. - Faites respecter
expetnbfavec une petite tolérance d'horloge, 60 à 120 secondes. - Pour les ID tokens, vérifiez en plus que le
noncecorrespond à celui envoyé, etazplorsque plusieurs audiences sont présentes. - Ensuite seulement, autorisez. Une signature valide signifie que l'AS a émis le token. Elle ne signifie pas que cet appelant peut supprimer cet enregistrement. Contrôlez scopes et rôles endpoint par endpoint.
En ASP.NET Core, l'essentiel tient dans la configuration :
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = "https://id.example.com",
ValidAudience = "api://orders",
ValidAlgorithms = new[] { "RS256" },
ClockSkew = TimeSpan.FromSeconds(60)
};
Des réglages équivalents existent dans jose pour Node, spring-security-oauth2-resource-server pour Java, et authlib pour Python. Utilisez une bibliothèque maintenue. Le parsing JWT artisanal, c'est ainsi que naissent les incidents alg: none. Pour une vision plus large du durcissement de vos endpoints, consultez notre guide des bonnes pratiques de sécurité des API.
Où vivent les tokens dans le navigateur
La vérité qui dérange : il n'existe aucun emplacement parfaitement sûr pour un token dans du JavaScript navigateur. localStorage survit à une XSS exactement le temps nécessaire pour l'exfiltrer. Les tokens en mémoire font mieux, mais meurent au rafraîchissement de la page et cèdent tout de même face à une injection de script qui détourne votre client HTTP.
Le pattern que nous recommandons pour tout projet sérieux est le Backend for Frontend (BFF). La chorégraphie OAuth se déroule côté serveur. Les tokens n'atteignent jamais le navigateur. La SPA reçoit un cookie HttpOnly, Secure, SameSite lié à une session serveur, et le BFF attache l'access token aux appels sortants. Une XSS peut encore exploiter la session tant que la page est ouverte, mais elle ne peut plus dérober un refresh token et repartir avec un accès persistant. Un bénéfice collatéral appréciable au regard du RGPD : moins de données de session exposées côté client, c'est aussi une surface de fuite en moins à documenter en cas d'incident.
Où que vivent vos refresh tokens, faites-les tourner. Chaque rafraîchissement émet un nouveau refresh token et invalide l'ancien. Si un token déjà utilisé se présente à nouveau, c'est votre signal de vol : révoquez toute la famille de tokens et forcez une réauthentification. La plupart des fournisseurs matures le prennent en charge nativement, mais la fonction est désactivée par défaut plus souvent qu'on ne le croit. Les tokens sender constrained via DPoP vont plus loin en liant le token à une clé détenue par le client, et le support progresse régulièrement.
Les défaillances que nous retrouvons sans cesse
- Des ID tokens utilisés comme identifiants d'API. Le RS accepte n'importe quel JWT à la signature valide sans jamais vérifier
aud. Correctif : des contrôles d'audience partout. - Une correspondance de redirect URI laxiste. Un wildcard plus une seule redirection ouverte sur un sous-domaine correspondant, et vos codes d'autorisation sont volés.
stateetnonceabsents. CSRF de connexion et fixation de session, discrètement exploitables pendant des années.- Un token universel pour tous les services. Pas de token par audience, pas de token exchange. Un seul pod compromis peut tout appeler. C'est précisément la défaillance que l'architecture Zero Trust est conçue pour contenir.
- Des access tokens de 24 heures sans aucun mécanisme de révocation. Quand un ordinateur portable est volé, « attendez demain » n'est pas un plan de réponse à incident.
- Des applications mobiles qui utilisent des schémas d'URI personnalisés pour les redirections. N'importe quelle application installée peut enregistrer le même schéma et intercepter le code. Utilisez des redirections https vérifiées : App Links sur Android, Universal Links sur iOS.
- Des secrets clients embarqués dans des SPA et des binaires mobiles. Un client public ne peut pas garder de secret. C'est exactement à cela que sert PKCE.
Développer, acheter ou auto-héberger
Ne développez jamais votre propre serveur d'autorisation. La surface du protocole (endpoints de tokens, consentement, rotation des clés, gestion de session, révocation) est immense et hostile. La vraie décision se joue entre managé et auto-hébergé :
- Managé (Auth0, Cognito, Entra External ID) : mise en production la plus rapide, défauts solides, tarification par utilisateur actif qui paraît dérisoire au début et douloureuse à l'échelle. D'expérience, la conversation tarifaire commence généralement quelque part dans les dizaines de milliers d'utilisateurs actifs mensuels.
- Auto-hébergé (Keycloak, Zitadel, Ory Hydra, Authentik) : contrôle total, résidence des données, aucun coût par utilisateur. La maîtrise de la localisation des données pèse lourd pour les organisations soumises au RGPD ou à des exigences de souveraineté, un point sensible sur le marché européen comme pour les acteurs francophones qui servent plusieurs juridictions, de Paris à Tunis. En contrepartie, vous assumez les montées de version, le durcissement, la disponibilité et la gestion des clés. Budgétez du vrai temps d'ingénierie, pas un week-end.
Quel que soit votre choix, exigez : une certification OIDC, le support de PKCE et de la rotation des refresh tokens, des audiences par API, des durées de vie courtes que vous contrôlez, et le support de WebAuthn, car la connexion par mot de passe vit ses dernières années. Si les passkeys figurent sur votre feuille de route, et ils devraient y figurer, OIDC reste le véhicule de livraison : notre article sur les passkeys et l'authentification sans mot de passe explique comment les pièces s'assemblent.
Le protocole n'est plus la difficulté. La discipline, si : redirections exactes, PKCE obligatoire, tokens restreints par audience, durées de vie courtes, rotation avec détection de réutilisation, et checklists de validation appliquées en revue de code. Les équipes qui intègrent ces six habitudes cessent tout simplement d'avoir des incidents OAuth.
Comment Innovation T peut vous aider
Innovation T conçoit et construit des infrastructures d'identité au quotidien : intégrations OIDC, architectures BFF pour SPA, déploiements Keycloak et IdP cloud, token exchange pour parcs de microservices, et audits d'implémentations OAuth existantes face au référentiel 2.1. Nous avons rencontré chacune des défaillances ci-dessus sur le terrain, et nous savons les corriger sans casser les sessions de vos utilisateurs.
Que vous choisissiez un fournisseur d'identité, démêliez un vieux flux implicite ou durcissiez un parc d'API, découvrez nos services ou échangez avec notre équipe. Nous vous dirons sans détour quoi corriger en premier.
Prêt à construire avec Innovation T ?
Qu'il s'agisse de sécurité, de croissance ou d'ingénierie, notre équipe peut vous aider à livrer dans les meilleures conditions.