Aller au contenu
medium

Sécurité opérationnelle IAM

21 min de lecture

Un système IAM mal opéré devient une cible de choix. Tokens trop longs, logs absents, secrets jamais renouvelés, pas de runbook... Ce guide couvre les mesures de hardening essentielles, l'observabilité à mettre en place, et les procédures de réponse aux incidents. Parce que déployer Keycloak ne suffit pas, il faut l'opérer de manière sécurisée.

Ce guide vous donne les clés pour opérer un système IAM en production. À la fin, vous saurez :

  • Identifier les menaces courantes : phishing, token theft, session hijacking
  • Appliquer les mesures de hardening : PKCE, durées courtes, rotation
  • Observer votre IAM : logs, métriques, alertes
  • Répondre aux incidents : playbooks, révocation, communication

Prérequis : avoir lu les guides OAuth 2.x, OIDC et MFA/WebAuthn.

Cinq familles d'attaques suffisent à couvrir l'essentiel de ce que subit un fournisseur d'identité en production. Elles ne visent pas toutes la même chose : certaines cherchent le mot de passe, d'autres se contentent d'un jeton déjà émis, ce qui leur permet de contourner entièrement l'authentification et le MFA. Chaque section décrit le vecteur puis les mesures qui le neutralisent, afin que vous puissiez relier une contre-mesure à une menace précise plutôt que d'empiler des réglages.

L'attaquant crée un faux site ou un email qui imite votre page de connexion, et capture ce que l'utilisateur y saisit. La variante moderne relaie la saisie en temps réel vers le vrai service, ce qui lui permet de récupérer aussi le code OTP au passage : un MFA par SMS ou par application d'authentification ne protège donc pas contre ce scénario. Seules les méthodes qui vérifient l'origine du site, comme WebAuthn et les passkeys, résistent structurellement.

VarianteDescriptionCible
Phishing classiqueFaux formulaire de loginMot de passe
Phishing TOTPCapture OTP en temps réelMFA classique
OAuth phishingFausse page d'autorisationCode d'autorisation
Spear phishingCiblé sur une personne (admin, finance)Comptes à privilèges

Mitigation :

  • MFA phishing-resistant (WebAuthn, passkeys)
  • Formation des utilisateurs
  • Filtrage email (SPF, DKIM, DMARC)

Voler un jeton déjà émis dispense l'attaquant de connaître le mot de passe et de passer le MFA : il rejoue simplement l'identité de la victime auprès des API. Le refresh token est la cible la plus rentable, puisqu'il permet de régénérer des access tokens bien après la fin de la session. Les quatre vecteurs ci-dessous mènent tous au même résultat, mais se corrigent à des endroits différents du code.

VecteurCommentImpact
XSSJavaScript malveillant lit le token en mémoireAccès API
CSRFL'utilisateur exécute une action sans le savoirChangement d'état
Log exposureToken loggé en clairPersistence de l'attaque
Man-in-the-MiddleInterception réseau (HTTP, proxy mal configuré)Tout

Mitigation :

  • Cookies HttpOnly, Secure, SameSite=Strict
  • Durées courtes (access token 5-15 min)
  • Rotation des refresh tokens
  • Validation de l'audience

Ces deux attaques ciblent le mécanisme de session plutôt que les credentials. Elles sont souvent sous-estimées car elles ne nécessitent pas de casser un mot de passe.

AttaqueDescription
Session hijackingL'attaquant vole un session ID existant
Session fixationL'attaquant force un session ID connu, puis attend que l'utilisateur se connecte

Mitigation :

  • Régénérer le session ID après login
  • Lier la session à l'IP / user-agent (avec prudence)
  • Durée de session limitée

L'attaquant dispose déjà d'un accès légitime et cherche à en dépasser les limites. La faille se trouve rarement dans l'IdP lui-même : elle vient presque toujours d'une application qui fait confiance aux claims du token sans revérifier les droits côté serveur, ou d'un identifiant d'objet manipulable dans une URL. Un contrôle masqué dans l'interface n'est pas un contrôle.

TypeExemple
VerticalUser → Admin
HorizontalUser A accède aux données de User B

Mitigation :

  • Valider les permissions côté serveur (pas seulement UI)
  • Principle of Least Privilege
  • Tests de politiques automatisés

Ici, l'attaquant ne vole rien de secret : il réutilise une requête ou un jeton valides interceptés une première fois. La parade consiste à rendre chaque échange non rejouable, en y injectant une valeur à usage unique. Le nonce remplit ce rôle dans le flux OIDC, et le jti identifie de façon unique chaque JWT émis, ce qui permet au service destinataire de refuser une seconde présentation.

Mitigation :

  • nonce dans les requêtes OIDC
  • Durées courtes + jti (JWT ID) unique
  • Token binding (lié à la session TLS)

Le durcissement d'un IAM se joue sur quatre terrains : les flux OAuth/OIDC, la validation des JWT côté service consommateur, les sessions navigateur et la gestion des clés. Aucun ne compense les faiblesses d'un autre, un JWT parfaitement validé ne sert à rien si le cookie de session part sans HttpOnly. Prenez-les dans l'ordre, chacun se vérifie indépendamment.

Ces cinq réglages se posent dans la configuration de l'IdP et du client, sans écrire de code. Les deux validations marquées « Critique » sont celles qu'on oublie le plus souvent : sans elles, un token émis pour une autre application ou par un autre émetteur est accepté sans broncher.

MesurePourquoiImpact
PKCE obligatoireEmpêche l'interception du codeTous les clients
Access token 5-15 minLimite la fenêtre d'exploitationRefresh plus fréquent
Refresh token rotationChaque usage génère un nouveau refreshDétecte le vol
Audience validationEmpêche l'utilisation d'un token sur un autre serviceCritique
Issuer validationVérifie que le token vient du bon IdPCritique

Un JWT n'est pas chiffré, seulement signé : n'importe qui peut lire sa charge utile, et c'est la vérification de signature qui fait foi. L'ordre des contrôles ci-dessous compte, la signature d'abord, les claims ensuite : lire iss ou aud dans un jeton dont la signature n'a pas été validée revient à faire confiance à l'attaquant. Notez aussi le paramètre algorithms passé explicitement, qui interdit à l'appelant d'imposer son propre algorithme.

// Checklist de validation JWT
function validateToken(token) {
const decoded = jwt.decode(token, { complete: true });
// 1. Signature valide
jwt.verify(token, publicKey, { algorithms: ['RS256'] });
// 2. Issuer attendu
if (decoded.payload.iss !== 'https://auth.example.com') throw new Error('Invalid issuer');
// 3. Audience correcte
if (!decoded.payload.aud.includes('my-api')) throw new Error('Invalid audience');
// 4. Non expiré
if (decoded.payload.exp < Date.now() / 1000) throw new Error('Token expired');
// 5. Not Before respecté
if (decoded.payload.nbf > Date.now() / 1000) throw new Error('Token not yet valid');
return decoded.payload;
}

Deux durées coexistent et doivent être réglées séparément : le délai d'inactivité, qui déconnecte un poste laissé sans surveillance, et la durée absolue, qui force une réauthentification même sur une session active. La régénération de l'identifiant après élévation de privilège est ce qui neutralise la session fixation.

ParamètreRecommandation
Durée de session15-30 min inactive, 8h max absolue
Cookie flagsHttpOnly, Secure, SameSite=Strict
Régénération IDAprès chaque élévation de privilège
InvalidationLogout = suppression côté serveur

Les clés de signature et les client secrets sont les seuls éléments dont la compromission permet de fabriquer des identités valides, indétectables par la validation classique. Ils méritent donc un traitement distinct du reste de la configuration : stockage externalisé, renouvellement planifié, et journalisation de chaque lecture.

  1. Rotation régulière

    Rotez les signing keys tous les 90 jours (automatisé).

  2. Secret management

    Utilisez un vault (HashiCorp Vault, AWS Secrets Manager).

  3. Pas de secrets dans le code

    Variables d'environnement ou fichiers montés, jamais en dur.

  4. Audit des accès

    Loggez qui accède aux secrets.

Une attaque sur l'identité ne provoque aucune panne : les connexions réussissent, les tokens sont valides, rien ne tombe. Sans instrumentation, elle reste invisible jusqu'à la fuite de données. L'objectif de cette partie est donc de rendre observable ce qui, par nature, ressemble à du trafic normal, en s'appuyant sur les écarts de comportement plutôt que sur les erreurs.

Les trois types de signaux répondent à des questions différentes : les logs disent ce qui s'est passé et pour qui, les métriques signalent qu'une tendance dévie, les traces relient une authentification au parcours applicatif qui l'a suivie.

PilierDonnées IAM
LogsAuthentifications, autorisations, erreurs
MétriquesLatence, taux de succès/échec, MFA adoption
TracesParcours utilisateur, corrélation avec les apps

La colonne Détails à capturer vaut autant que la ligne elle-même : un log de connexion sans adresse IP ni user-agent ne permet aucune corrélation ultérieure. Attention aussi à ce que vous n'écrivez pas : les valeurs de tokens et de mots de passe n'ont jamais leur place dans un journal, qui est généralement bien moins protégé que l'IdP.

ÉvénementPrioritéDétails à capturer
Login success/failureHauteUser, IP, user-agent, timestamp, MFA utilisé
Token issuanceHauteClient, scopes, audience
Token refreshMoyenneRefresh token ID, rotation
LogoutMoyenneUser, session ID
Password changeHauteUser, IP, méthode (self/admin)
MFA enrollment/unenrollHauteUser, type d'authenticator
Admin actionsCritiqueQui, quoi, sur qui

Les seuils ci-dessous sont des points de départ, à recalibrer sur votre trafic réel après quelques semaines d'observation. Deux d'entre eux méritent une attention particulière : une chute brutale du nombre de sessions actives trahit souvent une panne, tandis qu'un taux d'échec MFA élevé est le signe caractéristique d'une campagne de MFA fatigue, où l'attaquant bombarde la victime de demandes de validation.

MétriqueAlerte si
Login failure rate> 5% sur 5 min
MFA failure rate> 10% (possible MFA fatigue attack)
Token refresh rateSpike inhabituel
Latency P99 auth> 2s
Active sessionsSpike ou chute brutale

Aucune des lignes ci-dessous ne justifierait une alerte à elle seule : un changement de mot de passe est banal, une connexion nocturne aussi. C'est leur accumulation sur une même identité dans un court intervalle qui fait le signal. Construisez vos règles de détection sur des combinaisons d'attributs, sinon vous choisirez entre trop d'alertes et aucune.

User: alice@example.com
IP: 203.0.113.42 (nouveau pays: RU)
Action: Password change
Time: 03:47 UTC (inhabituel)
MFA: OTP (pas WebAuthn habituel)
→ ALERTE : Possible account takeover

Un incident d'identité se caractérise par sa vitesse de propagation : tant que l'accès n'est pas coupé, l'attaquant continue d'agir avec une identité valide. La priorité est donc toujours le confinement, l'investigation vient après. Ces procédures s'écrivent et se répètent à froid, parce qu'improviser une révocation globale à trois heures du matin coûte beaucoup plus cher que l'attaque elle-même.

Le classement par gravité détermine qui est réveillé et sous quel délai. Notez la dernière ligne : l'indisponibilité de l'IdP n'est pas une compromission, mais elle bloque toutes les authentifications de toutes les applications qui en dépendent.

IncidentGravitéExemples
Credential compromiseCritiqueMot de passe admin fuité
Session hijackHauteToken volé, accès non autorisé
MFA bypassCritiqueFaille dans le flow MFA
Privilege escalationCritiqueUser devient admin
DoS sur l'IdPHauteIdP indisponible = personne ne peut se connecter

Ce déroulé s'applique dès qu'un mot de passe est soupçonné d'avoir fuité, sans attendre la confirmation. L'étape de confinement doit précéder l'investigation : révoquer d'abord, comprendre ensuite. Attention au piège classique, changer le mot de passe sans invalider les refresh tokens laisse l'attaquant connecté.

  1. Containment immédiat

    • Révoquer toutes les sessions de l'utilisateur
    • Invalider tous les refresh tokens
    • Désactiver le compte si nécessaire
  2. Investigation

    • Quand le credential a-t-il été compromis ?
    • Quelles actions ont été effectuées ?
    • D'autres comptes sont-ils affectés ?
  3. Remediation

    • Forcer un changement de mot de passe
    • Réenrôler le MFA
    • Vérifier les modifications (email, permissions)
  4. Communication

    • Informer l'utilisateur
    • Notifier le management si données sensibles
    • Déclaration réglementaire si nécessaire (RGPD, etc.)
  5. Post-mortem

    • Comment l'attaque s'est-elle produite ?
    • Quelles mesures pour éviter la récidive ?

Le vol de jeton se traite différemment du vol de credential, parce que le compte n'est pas nécessairement compromis. Tout commence par l'identification du type de jeton dérobé : un access token JWT expirera de lui-même en quelques minutes, alors qu'un refresh token laisse la porte ouverte des jours durant s'il n'est pas explicitement révoqué.

  1. Identifier le scope

    • Quel token ? Access, refresh, session ?
    • Quel utilisateur / service account ?
    • Depuis quand ?
  2. Révoquer

    • Invalider le token (si token opaque + store)
    • Révoquer le refresh token
    • Terminer la session
  3. Analyser l'impact

    • Quelles API ont été appelées ?
    • Quelles données ont été accédées ?
  4. Renforcer

    • Réduire la durée des tokens
    • Activer la rotation des refresh tokens
    • Ajouter token binding si possible

Savoir couper un accès en urgence suppose d'avoir choisi le bon format de jeton au moment de la conception. Un JWT autoportant se valide sans appeler l'IdP, ce qui le rend rapide mais irrévocable individuellement avant son expiration : c'est le compromis central de l'architecture, et il se paie le jour de l'incident.

Ce tableau se lit comme une aide à la conception autant qu'à la réaction. La première ligne est la plus contraignante : avec des access tokens JWT, votre seul levier reste la durée de vie, d'où la recommandation de 5 à 15 minutes.

Type de tokenStratégie de révocation
Access token (JWT)Durée courte (5-15 min), pas de révocation individuelle
Access token (opaque)Lookup en base, révocation immédiate
Refresh tokenStore côté serveur, révocation par rotation ou explicite
SessionStore côté serveur, invalidation immédiate

Réservez cette manoeuvre aux compromissions majeures : déconnecter un realm entier reconnecte tout le monde en même temps, ce qui provoque une interruption visible et une vague de réauthentifications sur l'IdP. Les deux appels d'administration Keycloak ci-dessous couvrent le cas global et le cas ciblé sur un utilisateur.

Fenêtre de terminal
# Keycloak : révoquer toutes les sessions d'un realm
POST /admin/realms/{realm}/logout-all
# Keycloak : révoquer les sessions d'un utilisateur
POST /admin/realms/{realm}/users/{userId}/logout

Côté resource server, vérifiez si le token est toujours valide :

Fenêtre de terminal
POST /oauth2/introspect
Content-Type: application/x-www-form-urlencoded
token=eyJhbGci...&token_type_hint=access_token

Réponse :

{
"active": false,
"reason": "Token revoked"
}

Renouveler une clé ou un secret en production se fait toujours sans coupure, en faisant coexister temporairement l'ancien et le nouveau. Le principe est identique dans les deux cas traités ici : publier le nouveau, basculer, attendre que l'ancien ne soit plus utilisé, puis seulement le retirer. Inverser ces deux dernières étapes provoque une panne d'authentification généralisée.

Cette séquence repose sur le JWKS, le point d'exposition des clés publiques de l'IdP, capable d'en publier plusieurs simultanément. Chaque token porte dans son en-tête l'identifiant kid de la clé qui l'a signé, ce qui permet aux services de valider indifféremment les anciens et les nouveaux jetons pendant la transition.

  1. Générer une nouvelle clé

    Ajouter à la JWKS sans supprimer l'ancienne.

  2. Publier la nouvelle clé

    La JWKS expose maintenant 2 clés (ancienne + nouvelle).

  3. Basculer la signature

    L'IdP signe les nouveaux tokens avec la nouvelle clé.

  4. Attendre l'expiration

    Les anciens tokens expirent naturellement.

  5. Supprimer l'ancienne clé

    Retirer de la JWKS après expiration du plus long token.

Même logique côté application, à une réserve près : tous les IdP ne gèrent pas nativement deux secrets valides pour un même client. Vérifiez ce point avant de planifier la rotation, sinon l'étape 2 vous imposera une fenêtre de coupure au lieu d'un recouvrement.

ÉtapeAction
1Générer un nouveau secret
2Configurer l'application avec le nouveau (dual-secret)
3Tester que le nouveau fonctionne
4Révoquer l'ancien secret
5Supprimer l'ancien des configurations

Les deux listes ci-dessous condensent tout ce qui précède en points vérifiables. La distinction n'est pas cosmétique : la première regroupe des réglages ponctuels qui se posent une fois et se contrôlent avant l'ouverture au public, la seconde des activités récurrentes qui perdent tout intérêt si personne n'en porte la responsabilité dans la durée.

Ces sept points se vérifient sur la configuration, sans dépendre d'un outil externe. Aucun ne devrait rester non coché au moment de la bascule.

  • PKCE activé sur tous les clients
  • Access tokens ≤ 15 min
  • Refresh token rotation activée
  • Cookies HttpOnly, Secure, SameSite=Strict
  • MFA obligatoire pour les admins
  • Validation iss, aud, exp, nbf sur tous les tokens
  • Secrets dans un vault, pas dans le code

Chacun de ces points suppose une échéance et un responsable nommés. Une rotation de clés « planifiée » sans date dans le calendrier ne se produit jamais, et des playbooks écrits une fois pour l'audit ne servent à rien s'ils ne sont pas relus quand l'architecture change.

  • Logs envoyés au SIEM
  • Alertes configurées (failure rate, anomalies)
  • Rotation des signing keys planifiée (90 jours)
  • Playbooks de réponse aux incidents documentés
  • Tests de pénétration réguliers (focus auth)
  • Revue des permissions et accès admin (trimestriel)

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn