OAuth 2.0 (RFC 6749, 2012) est un protocole de délégation d'autorisation qui permet à un client d'obtenir un access token pour appeler une API au nom d'un utilisateur, sans que l'utilisateur ne partage ses credentials avec ce client. C'est le protocole le plus déployé du web moderne (intégrations SSO enterprise, SaaS, APIs publiques type Google / Stripe / GitHub / Slack) et aussi le plus souvent mal compris : OAuth 2.0 n'est pas un protocole d'authentification — cette confusion est la source n°1 de bugs d'implémentation IAM. L'authentification des utilisateurs est assurée par OIDC (OpenID Connect 1.0, 2014), couche complémentaire standardisée au-dessus d'OAuth 2.0 qui ajoute un ID Token JWT signé avec claims d'identité. Le protocole OAuth 2.0 définit 4 rôles (Resource Owner, Client, Authorization Server, Resource Server), 4 grant types utilisables en 2025 (Authorization Code + PKCE, Client Credentials, Device Code, Refresh Token) et 2 grants dépréciés par RFC 9700 Security BCP (2024) et OAuth 2.1 draft consolidé : Implicit Flow et Resource Owner Password Credentials (ROPC). Le flow dominant 2025 est Authorization Code + PKCE (Proof Key for Code Exchange, RFC 7636, 2015), devenu défaut universel même pour les clients avec client_secret selon OAuth 2.1. Cet article détaille la définition précise (et ce qu'OAuth n'est PAS), les 4 rôles, les 3 types de tokens (access / refresh / ID), le flow Authorization Code + PKCE avec diagramme pas-à-pas, les autres grants 2025 (Client Credentials pour M2M, Device Code pour IoT, Refresh), les grants dépréciés, OAuth 2.1 et les 10 recommandations RFC 9700, la confusion OAuth vs OIDC, les 5 attaques courantes et leur mitigation, la conception de scopes sécurisés, et les patterns d'implémentation 2025 pour SPA / mobile / M2M. Pour le contexte IAM global, voir Qu'est-ce que l'IAM.
1. Ce qu'OAuth 2.0 est (et ce qu'il n'est pas)
1.1 Définition précise
OAuth 2.0 répond à une question unique : « comment un client peut-il obtenir un accès délégué à une ressource protégée appartenant à un utilisateur, sans manipuler les credentials de cet utilisateur ? ».
Exemple concret : une application de gestion de dépenses veut lire les transactions d'un utilisateur depuis son compte bancaire. Sans OAuth, elle demanderait login + mot de passe bancaire à l'utilisateur — anti-pattern absolu. Avec OAuth, elle redirige l'utilisateur vers la banque, qui authentifie l'utilisateur, demande son consentement, et émet un access token scopé au minimum nécessaire (lecture transactions 90 jours). L'application utilise ce token pour appeler l'API bancaire. Les credentials bancaires ne quittent jamais le domaine de la banque.
1.2 Ce qu'OAuth 2.0 N'est PAS
| Anti-pattern fréquent | Pourquoi c'est faux |
|---|---|
| « OAuth authentifie l'utilisateur » | Non — OAuth autorise un accès. L'auth est OIDC. |
| « L'access token identifie l'utilisateur » | Non — il autorise un scope, pas nécessairement avec identité vérifiée. |
| « OAuth 2.0 est sécurisé par défaut » | Non — de nombreux pièges d'implémentation (redirect_uri, state, PKCE). |
| « JWT = OAuth » | Non — JWT est un format de token, OAuth est un framework de délégation. |
| « OAuth = SSO » | Non — SSO utilise généralement OIDC (au-dessus d'OAuth) ou SAML. |
1.3 Documents normatifs de référence
| Document | Année | Contenu |
|---|---|---|
| RFC 6749 | 2012 | OAuth 2.0 core framework |
| RFC 6750 | 2012 | Bearer Token Usage |
| RFC 7636 | 2015 | PKCE (Proof Key for Code Exchange) |
| RFC 7662 | 2015 | Token Introspection |
| RFC 8414 | 2018 | Authorization Server Metadata Discovery |
| RFC 8628 | 2019 | Device Authorization Grant |
| RFC 8725 | 2020 | JWT Best Current Practices |
| RFC 9126 | 2021 | Pushed Authorization Requests (PAR) |
| RFC 9449 | 2023 | DPoP (Demonstrating Proof-of-Possession) |
| RFC 9700 | 2024 | OAuth 2.0 Security Best Current Practice |
| OAuth 2.1 | draft | Consolidation des BCPs |
2. Les 4 rôles OAuth 2.0
┌─────────────────────┐
│ Resource Owner │
│ (l'utilisateur) │
└──────────┬──────────┘
│
│ authorize + consent
▼
┌────────────────────────────────┐
│ Authorization Server │
│ (IdP : Okta / Entra / Auth0) │
│ - émet access_token │
│ - émet refresh_token │
│ - émet id_token (si OIDC) │
└────────┬───────────────────────┘
│
│ délivre token
▼
┌────────────────┐ API call + Bearer token ┌──────────────────────┐
│ Client │ ─────────────────────────► │ Resource Server │
│ (application │ │ (API protégée) │
│ qui demande │ └──────────────────────┘
│ l'accès) │
└────────────────┘| Rôle | Définition | Exemple |
|---|---|---|
| Resource Owner | Entité qui détient la ressource (utilisateur humain le plus souvent) | Alice, titulaire de son compte bancaire |
| Client | Application qui demande l'accès à la ressource | App de gestion de dépenses tierce |
| Authorization Server (AS) | Émet les tokens après authentification Resource Owner + consentement | Auth server de la banque |
| Resource Server (RS) | API qui héberge les ressources protégées | API bancaire /transactions |
3. Les 3 types de tokens OAuth / OIDC
3.1 Access Token
- Destinataire : Resource Server (l'API).
- Format : JWT signé OU opaque (string aléatoire lookupé via token introspection).
- Durée : courte, 15 min à 1 heure typiquement.
- Contenu type (JWT) :
iss,sub,aud,exp,scope,client_id. - Transmission :
Authorization: Bearer <token>en header HTTP.
// Exemple Access Token JWT payload
{
"iss": "https://auth.example.com",
"sub": "user-abc123",
"aud": "https://api.example.com",
"exp": 1745488000,
"iat": 1745484400,
"scope": "transactions:read accounts:read",
"client_id": "mobile-app-v2"
}3.2 Refresh Token
- Destinataire : Authorization Server uniquement — JAMAIS à une API.
- Format : opaque (string aléatoire).
- Durée : longue, jours à mois.
- Usage : obtenir un nouveau access_token quand l'ancien expire, sans nouvelle interaction utilisateur.
- Sécurité : rotation obligatoire (nouveau refresh_token à chaque usage), stockage chiffré, invalidation sur logout.
3.3 ID Token (OIDC uniquement)
- Destinataire : Client uniquement — JAMAIS à une API.
- Format : JWT signé obligatoire (RS256, ES256, PS256).
- Durée : courte, 5-60 min.
- Contenu type : claims standardisés OIDC
iss,sub,aud,exp,iat,nonce,email,name,groups. - Usage : le client lit l'ID Token pour savoir qui est l'utilisateur connecté.
// Exemple ID Token payload OIDC
{
"iss": "https://auth.example.com",
"sub": "user-abc123",
"aud": "spa-app-web",
"exp": 1745487700,
"iat": 1745484400,
"nonce": "n-0S6_WzA2Mj",
"auth_time": 1745484400,
"amr": ["pwd", "mfa"],
"email": "alice@example.com",
"email_verified": true,
"name": "Alice Dupont"
}4. Flow dominant 2025 : Authorization Code + PKCE
4.1 Pourquoi PKCE partout
PKCE (Proof Key for Code Exchange, RFC 7636, 2015) protège contre l'interception de l'authorization code par un attaquant (app malveillante sur mobile, malware, MITM proxy). Sans PKCE, un code intercepté échange directement contre un access token. Avec PKCE, seul le client qui possède le code_verifier original peut échanger le code.
OAuth 2.1 draft et RFC 9700 (2024) recommandent PKCE sur tous les clients sans exception, y compris les clients confidentiels avec client_secret. Simplification de gouvernance et défense en profondeur.
4.2 Flow pas-à-pas
Authorization Code Flow + PKCE — étape par étape
─────────────────────────────────────────────────
1. Client génère : code_verifier (random 43-128 chars)
code_challenge = BASE64URL(SHA256(code_verifier))
2. Client → Authorization Server (redirect navigateur)
GET /authorize?
response_type=code
&client_id=mobile-app-v2
&redirect_uri=https://app.example.com/callback
&scope=transactions:read
&state=abc123random (CSRF protection)
&code_challenge=E9Melhoa2OwvFrEMT... (PKCE)
&code_challenge_method=S256
3. AS authentifie Resource Owner (password + MFA)
AS demande consentement sur les scopes
4. AS → Client (redirect navigateur avec code)
302 Location: https://app.example.com/callback?
code=SplxlOBeZQQYbYS6WxSbIA&state=abc123random
5. Client valide state = celui envoyé (CSRF check)
6. Client → AS (POST direct, TLS)
POST /token
grant_type=authorization_code
&code=SplxlOBeZQQYbYS6WxSbIA
&redirect_uri=https://app.example.com/callback
&client_id=mobile-app-v2
&code_verifier=dBjftJeZ4CVP... (PKCE proof)
7. AS vérifie SHA256(code_verifier) == code_challenge envoyé étape 2
8. AS → Client (response JSON)
{
"access_token": "eyJhbGc...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "tGzv3JOkF0XG5Qx2TlKWIA",
"id_token": "eyJhbGc..." (si OIDC)
}
9. Client appelle API avec Bearer token
GET /api/transactions
Authorization: Bearer eyJhbGc...4.3 Paramètres critiques à valider
Validations critiques Authorization Code Flow — checklist
──────────────────────────────────────────────────────────
Côté Authorization Server :
[ ] redirect_uri match EXACT (pas de wildcard, pas de préfixe) contre whitelist client
[ ] client_id existe et est actif
[ ] scope demandé subset des scopes autorisés au client
[ ] state paramètre présent (RECOMMANDÉ - CSRF)
[ ] code_challenge + code_challenge_method=S256 présents (OAuth 2.1)
[ ] nonce paramètre présent si OIDC (protection replay ID Token)
Côté Client (retour callback) :
[ ] state param retourné == celui envoyé
[ ] code present dans query params
[ ] échange côté serveur, pas en JS (sauf BFF pattern)
Côté Client (appel /token) :
[ ] code_verifier = celui généré pour ce flow (jamais réutilisé)
[ ] redirect_uri = même que étape 2
[ ] client_id identique
[ ] (client confidentiel) client_secret ou client_assertion signé JWT5. Autres grants OAuth 2.0 utilisables 2025
5.1 Client Credentials Grant (M2M)
Pour les appels machine-to-machine sans utilisateur impliqué. Le client s'authentifie directement avec ses credentials et obtient un access token.
POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
Authorization: Basic bW9iaWxlLWFwcC12MjpzZWNyZXQ=
grant_type=client_credentials
&scope=analytics:writeUsage typique : backend service qui appelle une API partenaire, CI/CD qui pushe des métriques, microservice → microservice avec workload identity federation.
5.2 Device Authorization Grant (RFC 8628)
Pour les appareils sans interface clavier ou avec UX limitée : Smart TV, IoT, CLI.
Device Authorization Flow
─────────────────────────
1. Device appelle /device_authorization, reçoit :
user_code: ABCD-1234
verification_uri: https://example.com/activate
expires_in: 600
2. Device affiche : "Allez sur example.com/activate et tapez ABCD-1234"
3. Utilisateur visite sur son téléphone, s'authentifie, entre le code
4. Device polle /token périodiquement
→ quand l'utilisateur a complété, reçoit les tokens5.3 Refresh Token Grant
Pour renouveler un access token expiré sans nouvelle interaction utilisateur.
POST /token HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded
grant_type=refresh_token
&refresh_token=tGzv3JOkF0XG5Qx2TlKWIA
&client_id=mobile-app-v2
&scope=transactions:readRotation obligatoire 2025 : RFC 9700 impose qu'à chaque usage, un nouveau refresh_token soit émis et l'ancien invalidé. Détection de vol : si un ancien refresh_token est réutilisé après rotation, l'Authorization Server doit invalider toute la chaîne (toutes les sessions actives).
6. Grants dépréciés par OAuth 2.1 / RFC 9700
6.1 Implicit Flow — déprécié
Retournait l'access_token directement dans l'URL fragment du callback. Vulnérable au token leakage via browser history, referer headers, extensions, proxies. Pas de refresh_token possible. Remplacé universellement par Auth Code + PKCE en 2024-2025.
6.2 Resource Owner Password Credentials (ROPC) — déprécié
Le client recevait directement le login/password de l'utilisateur et les échangeait contre token. Viole le principe même d'OAuth (délégation sans partage de credentials). Historiquement utilisé pour les apps mobiles first-party ; remplacé par Auth Code + PKCE.
7. OAuth 2.1 : la consolidation 2024-2025
OAuth 2.1 (draft Internet-Draft toujours en progression en 2025) consolide les bonnes pratiques accumulées depuis 2012. Changements par rapport à OAuth 2.0 :
| Changement | Impact |
|---|---|
| PKCE obligatoire sur tous les clients | Plus d'exception confidentiel vs public |
| Implicit Flow retiré | Migration SPA vers Auth Code + PKCE + BFF |
| ROPC retiré | Migration first-party apps vers Auth Code + PKCE |
| redirect_uri exact match obligatoire | Plus de wildcards ni préfixes partiels |
| Bearer token dans URI query interdit | Uniquement Authorization header |
| State parameter recommandé fortement | Protection CSRF standardisée |
| Refresh token rotation recommandée | Détection de vol |
7.1 Extensions sécurité modernes à connaître
- PAR (Pushed Authorization Requests, RFC 9126, 2021) — le client pousse la requête d'autorisation au AS en back-channel avant redirection, évite les paramètres sensibles dans l'URL.
- DPoP (Demonstrating Proof-of-Possession, RFC 9449, 2023) — token bound à une clé cryptographique côté client, même si le token fuite il est inutilisable sans la clé privée.
- JAR (JWT Secured Authorization Requests, RFC 9101, 2022) — requêtes signées JWT au lieu de query params clair.
- MTLS (RFC 8705) — authentification client par certificat mTLS au lieu de client_secret.
Adoption 2025 : PAR et DPoP émergents sur les flows haute sécurité (banque, paiement PSD2), MTLS dominant sur les APIs B2B enterprise.
8. OAuth 2.0 vs OIDC — clarifier une fois pour toutes
| Dimension | OAuth 2.0 | OIDC 1.0 (au-dessus d'OAuth) |
|---|---|---|
| Objectif | Délégation d'autorisation API | Authentification utilisateur |
| Token émis | access_token (+ refresh_token) | access_token + id_token + refresh_token |
| Format token | Libre (JWT ou opaque) | ID Token : JWT signé obligatoire |
| Claims standardisés | Non (scope, client_id) | Oui (iss, sub, aud, exp, email, name, nonce) |
| UserInfo endpoint | Non | Oui (/userinfo avec Bearer token) |
| Discovery endpoint | RFC 8414 | /.well-known/openid-configuration |
| Usage client | Appeler une API au nom d'un user | Connaître l'identité de l'user connecté |
| RFC / Standard | RFC 6749 + satellites | OpenID Foundation OIDC Core 1.0 |
Règle 2025 : pour implémenter un login utilisateur moderne (remplacer un login/password legacy), utiliser OIDC (qui inclut OAuth). Pour appeler une API tierce au nom d'un utilisateur (Stripe, GitHub, Google Workspace), utiliser OAuth 2.0 (avec OIDC sur l'Authorization Server en amont).
9. Les 5 attaques OAuth 2.0 courantes
9.1 redirect_uri manipulation
Si l'Authorization Server matche redirect_uri avec wildcard ou substring, l'attaquant peut détourner le code :
# Config laxiste vulnérable
allowed_redirect_uris = [
"https://app.example.com/*" # ❌ wildcard dangereux
]
# Attaquant crée https://app.example.com/callback/../../evil.tld
# ou exploite open redirect sur app.example.com
# Le code arrive chez l'attaquantMitigation : exact match redirect_uri uniquement, pas de wildcards, pas de path traversal autorisé. Valider côté AS.
9.2 CSRF via absence de state
Sans le paramètre state, un attaquant peut forger un flow OAuth qui lie les comptes de la victime au sien :
# Victim déjà connectée sur example.com
# Attaquant envoie un lien https://auth.example.com/authorize?redirect_uri=attacker
# Sans state, le callback se produit, victime lie son compte attaquantMitigation : state param aléatoire obligatoire côté client, stocké en session, vérifié au callback.
9.3 Authorization code interception sans PKCE
Sur mobile/SPA, le code retour dans l'URL peut être capté par une autre app (Android intent URL schemes collision).
Mitigation : PKCE obligatoire.
9.4 Token leakage
Access token dans referer headers, logs serveur, console navigateur, URL fragment Implicit Flow.
Mitigation : Authorization header uniquement, httpOnly cookies pour SPA via BFF, redaction agressive en logs.
9.5 Access token overprivileged
Un token avec scope admin:* utilisé pour une feature qui nécessite uniquement read:profile = blast radius maximal si le token fuite.
Mitigation : scopes granulaires par action, token scopé au minimum nécessaire, refresh token plus large mais non-exploitable côté API.
Pour le pendant offensif / détection de ces attaques, voir Méthodologie pentest API et Roadmap pentest web.
10. Concevoir des scopes OAuth 2.0 sécurisés
10.1 Principes
Les scopes sont le mécanisme d'autorisation granulaire d'OAuth 2.0. Mal conçus, ils produisent soit trop de friction (user consent fatigue) soit trop de privilège (blast radius).
Pattern correct 2025 :
Scopes par ressource + action + tenant si multi-tenant
───────────────────────────────────────────────────────
Exemples concrets :
transactions:read # lecture globale
transactions:read:account-id # lecture compte spécifique
transactions:write # création
accounts:admin # gestion du compte
users:delete # action destructrice séparée
Anti-patterns :
admin # trop large
full_access # ignore le principe de moindre privilège
api_user # ne dit rien sur les actions permises10.2 Scopes standardisés OIDC
OIDC définit des scopes standardisés :
| Scope | Claims retournés |
|---|---|
openid | sub — obligatoire pour OIDC |
profile | name, family_name, given_name, middle_name, nickname, picture, gender, birthdate, zoneinfo, locale, updated_at |
email | email, email_verified |
address | address (objet structuré) |
phone | phone_number, phone_number_verified |
offline_access | Émet un refresh_token |
11. Patterns d'implémentation 2025
11.1 SPA (React/Vue/Angular) — BFF pattern
Pattern BFF (Backend-For-Frontend) pour SPA — recommandé 2025
──────────────────────────────────────────────────────────────
Browser (SPA JS) ←───httpOnly Cookie───→ BFF (Node/Python/Go) ←──OAuth/OIDC──→ Auth Server
│
│
▼
Resource Server API
Avantages :
- Access token / Refresh token JAMAIS dans le browser
- Cookie httpOnly immunisé contre XSS
- CSRF gérable via SameSite + double-submit
- BFF fait le refresh token rotation, propage Cookie au browserLibrairies BFF 2025 : oauth2-proxy, duendesoftware/BFF (.NET), nginx-auth-request, Ory Oathkeeper.
11.2 Mobile natif — SDKs officiels
iOS : AppAuth-iOS (OpenID Foundation), Auth0 SDK. Android : AppAuth-Android, Auth0 SDK. Stockage tokens : Keychain Services iOS, EncryptedSharedPreferences Android.
11.3 Backend M2M — Client Credentials + workload identity
Pour les APIs internes, préférer Workload Identity federation (IRSA AWS, Workload Identity GKE, Azure WI) qui élimine le client_secret stocké. OAuth 2.0 Client Credentials reste utile pour partenaires B2B où federation n'est pas possible.
Voir Secrets management dans le cloud pour les patterns NHI + secrets.
11.4 Serveur OAuth 2.0 self-hosted — alternatives
Si besoin d'héberger son propre Authorization Server (souveraineté, cas d'usage spécifique) :
| Solution | Licence | Niveau |
|---|---|---|
| Keycloak (Red Hat) | Apache 2.0 | Mature, standard industrie OSS |
| Ory Hydra | Apache 2.0 | OIDC/OAuth 2.0 serverless-friendly |
| Authentik | MIT | Alternative cloud-native |
| Casdoor | Apache 2.0 | Émergent |
| ZITADEL | Apache 2.0 | Multi-tenant cloud-native |
La plupart des organisations 2025 préfèrent les IdP commerciaux (Okta, Auth0, Entra ID, Ping) pour workforce et CIAM — reviens vers self-hosted uniquement si souveraineté stricte ou ultra-personnalisation.
Points clés à retenir
- Définition précise : OAuth 2.0 = délégation d'autorisation (pas authentification). OIDC = authentification au-dessus d'OAuth 2.0.
- 4 rôles : Resource Owner, Client, Authorization Server, Resource Server.
- 3 tokens aux rôles distincts : Access Token (→ API), Refresh Token (→ AS uniquement), ID Token (→ Client uniquement, OIDC).
- Flow dominant 2025 : Authorization Code + PKCE (RFC 7636) — défaut universel même pour clients confidentiels selon OAuth 2.1 et RFC 9700.
- Grants utilisables 2025 : Authorization Code + PKCE (users), Client Credentials (M2M), Device Code (IoT), Refresh Token (rotation).
- Grants dépréciés : Implicit Flow (token leakage), ROPC (viole principe OAuth). Migration requise.
- OAuth 2.1 + RFC 9700 Security BCP (2024) : PKCE partout, redirect_uri exact match, state param, refresh rotation, Bearer en header uniquement.
- Extensions sécurité modernes : PAR (RFC 9126), DPoP (RFC 9449), JAR (RFC 9101), MTLS (RFC 8705).
- 5 attaques principales : redirect_uri manipulation, CSRF absence state, code interception sans PKCE, token leakage, access token overprivileged.
- Patterns implémentation : SPA → BFF avec httpOnly cookies, Mobile → AppAuth SDK + Keychain/Keystore, M2M → Workload Identity federation.
- Servers OSS : Keycloak, Ory Hydra, Authentik, ZITADEL. IdP commercial pour 80 % des cas workforce/CIAM.
Pour l'intégration d'OAuth/OIDC dans une stratégie IAM globale, voir Qu'est-ce que l'IAM. Pour les principes de secure coding applicables (token storage, état-less stateful), Principes de secure coding. Pour les tests offensifs OAuth en pentest, Méthodologie pentest API et Roadmap pentest web.







