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.
Qu'est-ce qu'OpenID Connect ?
Section intitulée « Qu'est-ce qu'OpenID Connect ? »OpenID Connect (OIDC) est un protocole d'authentification qui permet à une application de vérifier l'identité d'un utilisateur et de récupérer ses informations de profil, nom, adresse e-mail, auprès d'un service tiers de confiance. Publié en 2014 par l'OpenID Foundation, il est devenu le standard de l'authentification web moderne : chaque bouton « Se connecter avec Google » ou « Se connecter avec Microsoft » repose sur lui.
Concrètement, OIDC répond à une seule question : « qui est l'utilisateur connecté ? ». Votre application délègue la vérification du mot de passe, et du second facteur, à un fournisseur d'identité, appelé OpenID Provider, qui lui renvoie une preuve signée et infalsifiable : l'ID Token. L'application n'a jamais à stocker ni même à voir le mot de passe de l'utilisateur.
Analogie : OIDC fonctionne comme le contrôle d'identité à l'entrée d'un festival. Vous ne présentez pas votre pièce d'identité à chaque stand ; vous la montrez une seule fois à l'accueil, le fournisseur d'identité, qui vous remet un bracelet infalsifiable, l'ID Token. Chaque stand se contente de vérifier le bracelet, sans rejouer le contrôle.
C'est cette délégation qui rend le SSO (Single Sign-On) possible : un seul login sur le fournisseur d'identité ouvre l'accès à toutes les applications qui lui font confiance. OIDC ne réinvente rien, il s'appuie sur le protocole OAuth 2.0, auquel il ajoute une couche d'identité. Il joue un rôle comparable à SAML, le standard de fédération plus ancien, mais avec un jeton plus léger, du JSON plutôt que du XML, mieux adapté aux applications web et mobiles actuelles.
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)