OpenID Connect (OIDC) ajoute l’identité à OAuth 2.0. Là où OAuth répond “cette app peut accéder à l’API”, OIDC répond “cet utilisateur est alice@exemple.com”. C’est le standard derrière tous les boutons “Se connecter avec…” et la base du SSO (Single Sign-On) moderne. Un seul login, accès à toutes vos applications.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »Ce guide vous explique OpenID Connect (OIDC) — le standard pour l’authentification moderne. À la fin, vous saurez :
- Comprendre ce qu’OIDC ajoute à OAuth 2.0 (spoiler : l’identité)
- Décoder un ID Token et comprendre ses claims
- Valider correctement un JWT (signature, issuer, audience, expiration)
- Configurer une application avec Discovery et JWKS
Prérequis : avoir lu OAuth 2.x.
OAuth 2.0 + OIDC : la différence essentielle
Section intitulée « OAuth 2.0 + OIDC : la différence essentielle »OAuth 2.0 vous dit : “Cette application a le droit d’accéder à ces données.”
OIDC vous dit : “Voici qui est l’utilisateur connecté.”
Vocabulaire OIDC vs OAuth
Section intitulée « Vocabulaire OIDC vs OAuth »| Terme OAuth 2.0 | Équivalent OIDC |
|---|---|
| Authorization Server | OpenID Provider (OP) |
| Client | Relying Party (RP) |
| — | ID Token (nouveau) |
| — | UserInfo Endpoint (nouveau) |
L’ID Token : la preuve d’authentification
Section intitulée « L’ID Token : la preuve d’authentification »L’ID Token est un JWT (JSON Web Token) qui contient l’identité de l’utilisateur authentifié.
Structure d’un JWT
Section intitulée « Structure d’un JWT »Un JWT se compose de 3 parties séparées par des points :
header.payload.signatureChaque partie est encodée en base64url.
Exemple d’ID Token décodé
Section intitulée « Exemple d’ID Token décodé »Header :
{ "alg": "RS256", "typ": "JWT", "kid": "key-2024-02"}Payload (les claims) :
{ "iss": "https://auth.example.com", "sub": "user-123", "aud": "my-app-client-id", "exp": 1700000000, "iat": 1699996400, "nonce": "abc123xyz", "email": "alice@example.com", "name": "Alice Martin", "email_verified": true}Signature : permet de vérifier que le token n’a pas été modifié.
Claims standards OIDC
Section intitulée « Claims standards OIDC »| Claim | Description | Obligatoire |
|---|---|---|
iss | Issuer — URL de l’OP qui a émis le token | ✅ |
sub | Subject — identifiant unique de l’utilisateur | ✅ |
aud | Audience — client_id de l’application destinataire | ✅ |
exp | Expiration — timestamp UNIX | ✅ |
iat | Issued At — timestamp de création | ✅ |
nonce | Anti-replay — valeur envoyée à l’autorisation | ⚠️ Recommandé |
auth_time | Moment de l’authentification | Optionnel |
acr | Authentication Context Class Reference | Optionnel |
Claims de profil courants
Section intitulée « Claims de profil courants »| Claim | Description |
|---|---|
name | Nom complet |
given_name | Prénom |
family_name | Nom de famille |
email | Adresse email |
email_verified | Email vérifié (booléen) |
picture | URL de la photo de profil |
locale | Langue préférée |
Validation obligatoire de l’ID Token
Section intitulée « Validation obligatoire de l’ID Token »Checklist de validation
Section intitulée « Checklist de validation »-
Vérifier la signature
Récupérez les clés publiques via JWKS et vérifiez la signature. Utilisez le
kid(Key ID) du header pour trouver la bonne clé. -
Vérifier l’issuer (
iss)Doit correspondre exactement à votre OpenID Provider attendu. Une différence = token d’un autre IdP.
-
Vérifier l’audience (
aud)Doit contenir votre
client_id. Un token valide pour une autre app n’est pas valide pour vous. -
Vérifier l’expiration (
exp)Le token ne doit pas être expiré. Comparez avec l’heure actuelle (attention aux fuseaux horaires).
-
Vérifier le nonce
Si vous avez envoyé un
nonceà l’autorisation, vérifiez qu’il correspond. Protection contre les attaques de replay. -
Vérifier l’algorithme (
alg)Refusez
alg: none— signature désactivée. N’acceptez que les algorithmes attendus (RS256, ES256…).
Exemple de validation Node.js
Section intitulée « Exemple de validation Node.js »import jwt from 'jsonwebtoken';import jwksClient from 'jwks-rsa';
const client = jwksClient({ jwksUri: 'https://auth.example.com/.well-known/jwks.json', cache: true, cacheMaxAge: 600000, // 10 minutes});
async function validateIdToken(token) { // 1. Décoder le header pour obtenir le kid const decoded = jwt.decode(token, { complete: true }); if (!decoded) throw new Error('Invalid token format');
// 2. Récupérer la clé publique const key = await client.getSigningKey(decoded.header.kid); const publicKey = key.getPublicKey();
// 3. Vérifier le token complet const verified = jwt.verify(token, publicKey, { issuer: 'https://auth.example.com', audience: 'my-app-client-id', algorithms: ['RS256', 'ES256'], // Whitelist explicite });
// 4. Vérifier le nonce (si utilisé) if (verified.nonce !== expectedNonce) { throw new Error('Nonce mismatch'); }
return verified;}ID Token vs Access Token
Section intitulée « ID Token vs Access Token »Ces deux tokens ont des usages différents. Ne les confondez pas.
| Aspect | ID Token | Access Token |
|---|---|---|
| Consommé par | Le client (Relying Party) | L’API (Resource Server) |
| Contenu | Identité de l’utilisateur | Permissions (scopes) |
| Question | ”Qui est connecté ?" | "Quels accès sont autorisés ?” |
| Format | Toujours JWT | JWT ou opaque |
| Durée de vie | Courte (minutes) | Courte (minutes) |
| Envoyé à l’API | ❌ Non | ✅ Oui |
Discovery : l’auto-configuration
Section intitulée « Discovery : l’auto-configuration »Les OpenID Providers publient leur configuration à une URL standardisée :
https://auth.example.com/.well-known/openid-configurationExemple de réponse Discovery
Section intitulée « Exemple de réponse Discovery »{ "issuer": "https://auth.example.com", "authorization_endpoint": "https://auth.example.com/authorize", "token_endpoint": "https://auth.example.com/token", "userinfo_endpoint": "https://auth.example.com/userinfo", "jwks_uri": "https://auth.example.com/.well-known/jwks.json", "scopes_supported": ["openid", "profile", "email", "offline_access"], "response_types_supported": ["code", "id_token", "token"], "id_token_signing_alg_values_supported": ["RS256", "ES256"], "claims_supported": ["sub", "name", "email", "email_verified"]}Avantages de Discovery
Section intitulée « Avantages de Discovery »- Pas de configuration manuelle : l’application découvre les endpoints automatiquement
- Rotation transparente : les URLs peuvent changer sans casser les clients
- Validation de l’issuer : vérifiez que l’
issuerDiscovery correspond à celui attendu
JWKS : la rotation des clés
Section intitulée « JWKS : la rotation des clés »Le JWKS (JSON Web Key Set) contient les clés publiques pour vérifier les signatures des tokens.
Endpoint JWKS
Section intitulée « Endpoint JWKS »GET https://auth.example.com/.well-known/jwks.json{ "keys": [ { "kid": "key-2024-02", "kty": "RSA", "alg": "RS256", "use": "sig", "n": "0vx7agoebG...", "e": "AQAB" }, { "kid": "key-2024-01", "kty": "RSA", "alg": "RS256", "use": "sig", "n": "abc123...", "e": "AQAB" } ]}Gérer la rotation de clés
Section intitulée « Gérer la rotation de clés »Les clés de signature changent régulièrement (sécurité, compromission). Votre application doit :
-
Cacher les clés JWKS avec un TTL raisonnable (5-15 minutes)
-
Rafraîchir si un
kidinconnu apparaît dans un token -
Valider que le nouveau
kidprovient bien du bon endpoint JWKS
UserInfo Endpoint
Section intitulée « UserInfo Endpoint »Le UserInfo endpoint retourne des informations supplémentaires sur l’utilisateur authentifié.
curl -H "Authorization: Bearer <access_token>" \ https://auth.example.com/userinfoRéponse :
{ "sub": "user-123", "name": "Alice Martin", "email": "alice@example.com", "email_verified": true, "picture": "https://example.com/photos/alice.jpg"}ID Token vs UserInfo
Section intitulée « ID Token vs UserInfo »| Aspect | ID Token | UserInfo |
|---|---|---|
| Disponible | Au moment du login | À tout moment avec un access token valide |
| Format | JWT signé | JSON simple |
| Fraîcheur | Figé au moment de l’émission | Peut refléter des changements récents |
| Usage | Authentification initiale | Mise à jour du profil |
Gestion des sessions
Section intitulée « Gestion des sessions »Session côté IdP vs côté application
Section intitulée « Session côté IdP vs côté application »| Session | Gérée par | Durée |
|---|---|---|
| Session IdP | L’OpenID Provider | Longue (heures/jours) |
| Session application | Votre application | Configurable |
Ces sessions sont indépendantes. La fin de l’une n’implique pas automatiquement la fin de l’autre.
Single Sign-On (SSO)
Section intitulée « Single Sign-On (SSO) »Si l’utilisateur a déjà une session active sur l’IdP :
- Votre app redirige vers l’IdP
- L’IdP reconnaît l’utilisateur (session existante)
- L’IdP redirige immédiatement vers votre app avec les tokens
- Pas de login demandé
Single Logout (SLO)
Section intitulée « Single Logout (SLO) »Pour déconnecter l’utilisateur de toutes les applications :
- L’application appelle le end_session_endpoint de l’IdP
- L’IdP invalide sa session
- L’IdP notifie les autres applications (front-channel ou back-channel logout)
// Logout OIDCconst logoutUrl = new URL('https://auth.example.com/logout');logoutUrl.searchParams.set('id_token_hint', idToken);logoutUrl.searchParams.set('post_logout_redirect_uri', 'https://myapp.com/logged-out');window.location.href = logoutUrl.toString();Sessions sans état (stateless)
Section intitulée « Sessions sans état (stateless) »Avec des tokens JWT, vous pouvez avoir des sessions stateless :
- Pas de session serveur à maintenir
- Le token contient toutes les informations
- Problème : révocation difficile (attendre l’expiration)
Mitigation : tokens courts (15-30 min) + refresh tokens révocables côté serveur.
Scopes OIDC standards
Section intitulée « Scopes OIDC standards »| Scope | Claims retournés |
|---|---|
openid | sub (obligatoire pour OIDC) |
profile | name, family_name, given_name, picture, locale, etc. |
email | email, email_verified |
address | address (objet structuré) |
phone | phone_number, phone_number_verified |
offline_access | Obtenir un refresh token |
Flow complet OIDC avec PKCE
Section intitulée « Flow complet OIDC avec PKCE »-
L’utilisateur clique “Se connecter”
L’application génère un
state, unnonce, et uncode_verifier(PKCE). -
Redirection vers l’IdP
GET https://auth.example.com/authorize?response_type=code&client_id=my-app&redirect_uri=https://myapp.com/callback&scope=openid profile email&state=abc123&nonce=xyz789&code_challenge=SHA256(code_verifier)&code_challenge_method=S256 -
Authentification sur l’IdP
L’utilisateur entre ses credentials (et MFA si configuré).
-
Consentement
L’utilisateur accepte les scopes demandés (ou les a déjà acceptés).
-
Retour avec le code
GET https://myapp.com/callback?code=AUTH_CODE&state=abc123 -
Échange du code contre les tokens
Fenêtre de terminal POST https://auth.example.com/tokenContent-Type: application/x-www-form-urlencodedgrant_type=authorization_code&code=AUTH_CODE&redirect_uri=https://myapp.com/callback&client_id=my-app&code_verifier=ORIGINAL_VERIFIER -
Réception des tokens
{"access_token": "eyJhbGciOiJSUzI1Ni...","id_token": "eyJhbGciOiJSUzI1Ni...","refresh_token": "dGhpcyBpcyBhIHJlZn...","token_type": "Bearer","expires_in": 3600} -
Validation de l’ID Token
L’application valide signature, iss, aud, exp, nonce.
-
Session établie
L’application crée une session pour l’utilisateur.
Erreurs fréquentes
Section intitulée « Erreurs fréquentes »| Erreur | Conséquence | Solution |
|---|---|---|
Pas de validation aud | Token d’une autre app accepté | Toujours valider l’audience |
Accepter alg: none | Tokens forgés acceptés | Whitelist d’algorithmes |
Ignorer le nonce | Vulnérable au replay | Générer et valider un nonce |
| ID Token envoyé à l’API | Mauvais usage du token | Utiliser l’access token pour les APIs |
| Pas de cache JWKS | Latence à chaque validation | Cache avec TTL de 10-15 min |
À retenir
Section intitulée « À retenir »Références
Section intitulée « Références »- OpenID Connect Core 1.0
- OpenID Connect Discovery 1.0
- RFC 7517 — JSON Web Key (JWK)
- RFC 7519 — JSON Web Token (JWT)