OpenID Connect (OIDC) est une couche d'authentification standardisée en 2014 par la OpenID Foundation, construite au-dessus du framework d'autorisation OAuth 2.0 (RFC 6749, 2012). Sa fonction : permettre à une application (Relying Party) de vérifier l'identité d'un utilisateur authentifié par un OpenID Provider (Google, Microsoft, Okta, Auth0, Keycloak, Entra ID) via un ID Token au format JWT. Différence essentielle avec OAuth 2.0 : OAuth gère l'autorisation (accès à des ressources au nom de l'utilisateur), OIDC gère l'authentification (qui est l'utilisateur). En 2026, OIDC est le protocole standard pour le SSO d'entreprise, l'authentification des applications web modernes, et le Workload Identity Federation dans les pipelines CI/CD (remplacement des clés statiques cloud). Le flow recommandé est Authorization Code avec PKCE (RFC 7636) pour tous les clients publics, les flows Implicit et ROPC étant officiellement dépréciés par OAuth 2.1 (2024). Cet article détaille les définitions, les 5 flows, la structure des tokens, les attaques courantes (JWT alg:none, open redirect, token substitution), et les bonnes pratiques d'implémentation.
OAuth 2.0 vs OpenID Connect : la confusion à éliminer
OAuth 2.0 : framework d'autorisation
OAuth 2.0 permet à une application d'obtenir un accès délégué à des ressources appartenant à un utilisateur, sans partager son mot de passe. Exemple classique : une application comptable demande accès à vos transactions bancaires.
Scénario OAuth 2.0 :
Utilisateur → autorise App Comptable
App Comptable → reçoit Access Token → appelle API bancaire
API Bancaire → vérifie Access Token → retourne donnéesOAuth ne dit rien sur qui est l'utilisateur. Il dit seulement : « ce client a le droit d'accéder à cette ressource avec ce scope ».
OIDC : couche d'authentification
OpenID Connect ajoute un ID Token qui décrit l'utilisateur authentifié.
Scénario OIDC :
Utilisateur → se connecte via Google sur App MonSite
Google → émet Access Token + ID Token au client MonSite
MonSite → lit l'ID Token (JWT) → connaît l'identité vérifiéeL'ID Token est un JWT qui contient des claims standardisés (sub, email, name, iss, aud, exp, nonce) signés par l'OpenID Provider.
Les 3 rôles OIDC
OpenID Provider (OP)
aka Authorization Server, Identity Provider (IdP)
Exemple : Google, Microsoft Entra ID, Okta, Auth0, Keycloak
Rôle : authentifier l'utilisateur, émettre tokens
Relying Party (RP)
aka Client Application
Exemple : votre application web, mobile, SPA
Rôle : consommer l'ID Token pour connaître l'utilisateur
End User
L'utilisateur final qui s'authentifieLes 5 flows OIDC
1. Authorization Code + PKCE - flow recommandé 2026
Standard pour les clients publics (SPA, mobile, desktop) et fortement recommandé aussi pour clients confidentiels web server-side.
Étape 1 - Client génère PKCE :
code_verifier = random 43-128 chars
code_challenge = BASE64URL(SHA256(code_verifier))
Étape 2 - Redirection authorization :
GET https://op.example/authorize
?response_type=code
&client_id=xyz
&redirect_uri=https://app.example/callback
&scope=openid profile email
&state=<csrf_random>
&nonce=<replay_protection_random>
&code_challenge=<hash>
&code_challenge_method=S256
Étape 3 - Utilisateur s'authentifie chez OP
Login + MFA éventuel
Étape 4 - OP redirige vers le client avec un code :
GET https://app.example/callback?code=ABC123&state=<csrf_random>
Étape 5 - Client échange code contre tokens (backend ou SPA PKCE) :
POST https://op.example/token
grant_type=authorization_code
code=ABC123
redirect_uri=https://app.example/callback
client_id=xyz
code_verifier=<original_secret>
Étape 6 - OP valide code_verifier vs code_challenge, retourne :
{
"access_token": "...",
"id_token": "eyJhbG...",
"refresh_token": "...",
"token_type": "Bearer",
"expires_in": 3600
}2. Client Credentials - service-to-service
Utilisé quand deux services dialoguent sans utilisateur final. Exemple : microservice A appelle microservice B.
POST https://op.example/token
grant_type=client_credentials
client_id=service-a
client_secret=...
Réponse :
access_token + expires_in (pas d'ID Token car pas d'utilisateur)3. Device Authorization - IoT, TV
Pour les appareils sans clavier (TV connectée, device IoT). L'utilisateur valide sur un autre device (smartphone) en saisissant un code.
Device → POST /device_authorization → reçoit user_code, device_code, verification_uri
TV affiche : « Allez sur https://op.example/device et entrez ABC-123 »
Utilisateur se connecte sur smartphone avec ce code
Device polle /token avec device_code jusqu'à obtention4. Hybrid Flow
Combinaison Authorization Code + ID Token dans la réponse immédiate. Moins utilisé en 2026 car complexe. Utilisé dans certaines intégrations SSO enterprise legacy.
5. Implicit Flow (DÉPRÉCIÉ)
Flow historique pour SPA avant PKCE. Tokens retournés directement dans l'URL de redirection. Déprécié par OAuth 2.0 Security BCP et OAuth 2.1. Ne jamais utiliser en 2026 pour nouveaux déploiements.
Pourquoi déprécié :
Token dans URL = fuite via Referer, logs serveur, extensions navigateur
Pas de preuve de possession = replay possible
Authorization Code + PKCE résout tous ces problèmesFlow Resource Owner Password Credentials (DÉPRÉCIÉ)
L'utilisateur fournit son mot de passe directement au client (qui l'envoie au server pour obtenir un token). Déprécié par OAuth 2.1. Anti-pattern absolu : casse le principe même d'OAuth (pas de partage de mot de passe).
Structure d'un ID Token (JWT)
Un JWT est composé de trois parties séparées par des points : header.payload.signature.
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9
.
eyJpc3MiOiJodHRwczovL29wLmV4YW1wbGUiLCJzdWIiOiJ1c2VyXzEyMyIsImF1ZCI6ImNsaWVudF94eXoiLCJleHAiOjE3MzQ5MDAwMDAsImlhdCI6MTczNDg5NjQwMCwibm9uY2UiOiJhYmMxMjMiLCJlbWFpbCI6ImFsaWNlQGV4YW1wbGUuY29tIn0
.
signature_RSA256_base64urlHeader décodé
{
"alg": "RS256",
"typ": "JWT",
"kid": "123"
}Payload décodé (claims)
{
"iss": "https://op.example",
"sub": "user_123",
"aud": "client_xyz",
"exp": 1734900000,
"iat": 1734896400,
"nonce": "abc123",
"email": "alice@example.com",
"email_verified": true,
"name": "Alice Dupont"
}Claims standardisés
| Claim | Signification | Validation obligatoire |
|---|---|---|
iss | Issuer (OpenID Provider URL) | Oui (matcher config attendue) |
sub | Subject (ID utilisateur stable) | Oui (jamais changer entre sessions) |
aud | Audience (client_id destinataire) | Oui (doit contenir votre client_id) |
exp | Expiration timestamp (Unix) | Oui (vérifier non expiré) |
iat | Issued at | Recommandé |
nonce | Protection replay (fourni par client) | Oui (matcher envoyé) |
auth_time | Timestamp d'authentification | Optionnel |
acr | Authentication Context Class Reference (niveau) | Optionnel |
amr | Authentication Methods References | Optionnel |
Validation d'un ID Token : checklist
# Exemple Python avec PyJWT + cryptography
import jwt
import requests
# 1. Récupérer JWKS de l'OpenID Provider
JWKS_URL = "https://op.example/.well-known/jwks.json"
jwks_client = jwt.PyJWKClient(JWKS_URL)
def validate_id_token(id_token: str, expected_client_id: str, nonce_sent: str) -> dict:
# 2. Obtenir la clé publique correspondant au kid du header
signing_key = jwks_client.get_signing_key_from_jwt(id_token)
# 3. Valider signature, algorithme, issuer, audience, expiration
payload = jwt.decode(
id_token,
signing_key.key,
algorithms=["RS256"], # JAMAIS ["none"], jamais de mix HS256/RS256
audience=expected_client_id,
issuer="https://op.example",
options={"require": ["exp", "iat", "iss", "aud", "sub"]},
)
# 4. Vérifier le nonce
if payload.get("nonce") != nonce_sent:
raise ValueError("nonce mismatch - possible replay attack")
return payloadScopes OIDC standards
openid : obligatoire pour déclencher OIDC (sinon OAuth pur)
profile : name, family_name, given_name, picture, updated_at
email : email, email_verified
phone : phone_number, phone_number_verified
address : address (structured)
Scopes custom :
Exemples : "read:invoices", "write:reports"
Définis par chaque OpenID Provider, reçus dans l'Access TokenAttaques courantes et parades
Attaque 1 - JWT alg:none
Un attaquant modifie le header JWT pour mettre "alg": "none" et retire la signature. Si le validateur accepte none, il accepte tout token.
Parade :
Toujours whitelister les algorithmes acceptés (RS256, ES256)
Bannir explicitement "none"
Utiliser des bibliothèques qui refusent "none" par défaut (PyJWT 2.0+)Attaque 2 - Confusion HS256 / RS256
Si le validateur ne vérifie pas strictement l'algorithme, un attaquant signe un JWT avec HS256 en utilisant la clé publique RS256 comme secret HMAC.
Parade :
Toujours passer explicitement algorithms=["RS256"]
Ne jamais déduire l'algorithme du header uniquementAttaque 3 - Open redirect via redirect_uri
Un attaquant manipule le paramètre redirect_uri pour recevoir le code d'autorisation sur son propre domaine.
Parade :
Whitelister strictement les redirect_uri côté OP (exact match, pas regex)
Ne pas accepter les wildcards sur les redirect_uri
Valider côté client que le state correspondAttaque 4 - CSRF sans state
Sans paramètre state, un attaquant peut forger une requête qui lie son compte à la session victime.
Parade :
Toujours générer un state aléatoire et le valider au callback
Random cryptographique, au moins 128 bits d'entropie
Lier le state à la session utilisateur (cookie)Attaque 5 - Replay d'ID Token sans nonce
Sans nonce, un ID Token intercepté peut être rejoué.
Parade :
Toujours inclure un nonce aléatoire dans la requête authorize
Valider qu'il est présent dans l'ID Token reçu
Ne jamais réutiliser un nonceAttaque 6 - Token substitution (ID Token vs Access Token)
Une API qui accepte un ID Token comme Access Token est vulnérable à la substitution.
Parade :
L'ID Token a aud=client_id (pas l'API)
L'Access Token a aud=resource_server (l'API)
L'API valide explicitement aud et refuse les tokens avec mauvaise audienceAttaque 7 - SSRF via URI parameter
Certains paramètres OIDC (jwks_uri, logo_uri, request_uri) acceptent des URLs utilisateur qui peuvent être exploitées pour SSRF côté OP.
Parade :
Whitelister les domaines acceptés côté OP
Bloquer les IP privées et métadonnées cloud
Utiliser les recommandations OWASP SSRF Cheat SheetOIDC dans CI/CD : Workload Identity Federation
Depuis 2022-2023, OIDC est massivement adopté pour remplacer les clés statiques cloud (AWS access keys, GCP service account JSON, Azure app secrets) dans les pipelines CI/CD.
Principe
Le runner CI/CD émet un JWT OIDC signé avec des claims sur le contexte (repository, branch, environment, actor). Le cloud provider configuré en trust avec le provider OIDC du CI échange ce JWT contre des credentials court-durée (1-2 h).
GitHub Actions → AWS
name: deploy-to-aws
on: [push]
permissions:
id-token: write # requis pour émettre le JWT OIDC
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials via OIDC
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789:role/github-actions-deploy
aws-region: eu-west-3
- run: aws s3 sync ./dist s3://my-bucket/Côté AWS, configurer un Identity Provider pointant vers token.actions.githubusercontent.com et une IAM Role avec trust policy qui vérifie aud=sts.amazonaws.com et sub=repo:org/repo:ref:refs/heads/main.
Autres providers CI/CD avec OIDC natif
GitHub Actions : ✓ natif depuis 2021
GitLab CI : ✓ natif depuis 15.7 (2022)
CircleCI : ✓ natif depuis 2022
Bitbucket Pipelines : ✓ natif
Jenkins : ✓ via plugin OIDC
Terraform Cloud / HCP : ✓ Workload Identity natif
Destinations supportées :
AWS IAM Identity Provider
GCP Workload Identity Federation
Azure Federated Credentials
HashiCorp Vault JWT/OIDC auth method
Kubernetes ServiceAccount Projected TokensBibliothèques et frameworks 2026
Côté client (Relying Party)
JavaScript/TypeScript :
oidc-client-ts (successor oidc-client-js)
openid-client (Node.js backend)
NextAuth.js (Next.js)
Auth.js (framework-agnostic)
Python :
Authlib : complet et maintenu
requests-oauthlib : léger
mozilla-django-oidc : Django
Java :
Nimbus OAuth 2.0 SDK : référence
Spring Security OAuth2 : intégration Spring
Go :
golang.org/x/oauth2
github.com/coreos/go-oidc
Ruby :
omniauth-openid-connect
Rust :
openidconnect-rsCôté serveur (OpenID Provider self-hosted)
Keycloak (Red Hat OSS) : leader OSS, mature
Ory Hydra + Kratos : modulaire, cloud-native
Authentik (OSS) : moderne, alternative
Zitadel (OSS + SaaS) : multi-tenant natif
Authelia (OSS) : léger, self-hosting homelabSaaS OpenID Providers
Auth0 (Okta) : leader SaaS
Microsoft Entra ID : dominant entreprise M365
Okta Customer Identity : enterprise
Google Identity Platform : GCP, grand public via Google Sign-In
Amazon Cognito : AWS-friendly
Clerk : dev-friendly, moderne
Stytch : passwordless-first
WorkOS : SSO B2B dev-friendlyBonnes pratiques 2026
- Authorization Code + PKCE pour tous les nouveaux clients, publics ou confidentiels.
- Bannir Implicit et ROPC explicitement dans les politiques.
- Whitelister strict des redirect_uri (exact match, pas de wildcards).
- State et nonce aléatoires à chaque requête authorize, cryptographiquement sécurisés.
- Validation JWT via bibliothèque, avec
algorithms=["RS256"]explicite. - Refresh tokens avec rotation (RFC 6749 bis draft), jamais stockés en JavaScript.
- Tokens court-durée : Access Token 15 min max, Refresh Token 7-30 jours.
- Logout propre via
end_session_endpointOIDC + révocation côté OP. - Monitoring des flows : alertes sur anomalies (changement d'IP, nouveau device).
- Workload Identity Federation pour tout CI/CD, remplacer toutes les clés statiques cloud.
Points clés à retenir
- OIDC = couche d'authentification standardisée 2014 sur OAuth 2.0. Fournit un ID Token JWT avec l'identité vérifiée de l'utilisateur.
- OAuth 2.0 = framework d'autorisation (accès ressources). OIDC = authentification (qui est l'utilisateur). OIDC inclut OAuth 2.0 sous-jacent.
- Flow recommandé 2026 : Authorization Code + PKCE (RFC 7636) pour tout. Implicit et ROPC dépréciés par OAuth 2.1.
- ID Token = JWT destiné au client. Access Token = destiné à l'API. Ne jamais confondre les deux : vulnérabilité token substitution.
- Validation JWT obligatoire : signature (via JWKS),
iss,aud,exp,nonce. Toujours whitelister algorithmes. Banniralg:none. - 7 attaques courantes : alg:none, confusion HS256/RS256, open redirect, CSRF sans state, replay sans nonce, token substitution, SSRF via URI.
- Workload Identity Federation : remplacer les clés statiques cloud (AWS access keys, GCP JSON, Azure secrets) par JWT OIDC échangé contre credentials court-durée. Natif GitHub Actions, GitLab CI, CircleCI.
- OpenID Providers self-hosted : Keycloak, Ory Hydra+Kratos, Authentik, Zitadel. SaaS leaders : Auth0, Entra ID, Okta, Cognito, Clerk.
Pour comprendre comment sécuriser l'autorisation après authentification OIDC (A01 OWASP), voir Broken Access Control : explication, exemples et prévention. Pour sécuriser les entrées utilisateur reçues via le flow (redirect_uri, state, code), lire Validation des entrées : bonnes pratiques secure coding 2026. Pour resituer OIDC dans la roadmap AppSec complète d'un développeur, la roadmap AppSec Engineer 2026 détaille les étapes.





