Cybersécurité

Authentification forte et IAM : MFA, SSO, OAuth 2.0/OIDC et Keycloak

14 min de lecture

📍 Article de référence : Sécuriser les systèmes d’information : guide complet 2026
Ce tutoriel détaille la mise en œuvre opérationnelle d’un fournisseur d’identité moderne avec authentification forte. Pour la vue d’ensemble, consultez le guide de référence.

Le mot de passe seul est mort. Les chiffres du rapport Verizon DBIR 2025 sont sans appel : 22 % des compromissions initiales en 2024 exploitent des identifiants volés et 88 % des attaques contre les applications web reposent sur la réutilisation d’identifiants — souvent issus d’infostealers ayant exfiltré les credentials des navigateurs des utilisateurs des semaines avant l’attaque visible. La parade documentée et largement adoptée se résume à trois mots : authentification multi-facteurs, résistante au phishing, centralisée. Ce tutoriel construit un fournisseur d’identité open-source de niveau production avec Keycloak 26.x, active l’authentification TOTP puis WebAuthn/FIDO2, intègre une application web par OpenID Connect, et fédère l’authentification avec un annuaire LDAP/Active Directory existant.

Prérequis

  • Serveur Linux (Ubuntu 24.04 LTS, Debian 12 ou RHEL 9) avec 4 Go de RAM minimum et 2 vCPU.
  • Docker Engine 24+ ou Java 21 installés (Keycloak 26 fonctionne sur l’un ou l’autre).
  • Base de données PostgreSQL 16+ accessible (locale ou managée).
  • Nom de domaine résolvable (DNS) et certificat TLS valide — Let’s Encrypt ou autorité interne.
  • Niveau attendu : intermédiaire à avancé.
  • Temps estimé : 3 heures pour un déploiement initial, plus une journée pour fédérer LDAP et intégrer trois applications.

Étape 1 — Comprendre OAuth 2.0, OpenID Connect et les rôles

Avant tout déploiement, il est essentiel de poser les concepts. Confondre OAuth 2.0 (autorisation) et OpenID Connect (authentification) est la source numéro un d’erreurs d’intégration en production. OAuth 2.0 (RFC 6749, 2012) est un protocole d’autorisation : il permet à une application (le client) d’obtenir un accès délégué à une ressource au nom de l’utilisateur, sans connaître les identifiants de ce dernier. OpenID Connect (OIDC, spécification finale 2014, mise à jour en continu) est une couche d’authentification bâtie au-dessus d’OAuth 2.0 : il ajoute un ID Token au format JWT qui prouve l’identité de l’utilisateur authentifié.

Les rôles dans une architecture OIDC :

  • Resource Owner : l’utilisateur final qui possède l’identité et donne (ou non) son consentement.
  • OpenID Provider (OP) : le fournisseur d’identité — ici Keycloak — qui authentifie l’utilisateur et émet les jetons.
  • Relying Party (RP) : l’application cliente qui consomme les jetons pour authentifier ses utilisateurs.
  • Resource Server : une API consommée par l’application, qui valide les Access Tokens reçus.

Les flux à connaître : Authorization Code Flow with PKCE (le seul recommandé en 2026 pour les applications web et mobiles), Client Credentials Flow (machine-to-machine, sans utilisateur), Device Authorization Flow (RFC 8628, pour terminaux à entrée limitée comme TV ou IoT). Les flux historiques Implicit et Resource Owner Password Credentials sont obsolètes et bannis par la spec OAuth 2.1 — ne jamais les implémenter dans un nouveau projet.

Étape 2 — Déployer Keycloak 26 en Docker Compose

Keycloak 26.x est la branche maintenue en 2026. Depuis la version 17, la distribution est bâtie sur Quarkus, optimisée pour le démarrage rapide et la faible empreinte mémoire. Le déploiement via Docker Compose pour un environnement de pré-production ou un petit prod :

# /opt/keycloak/docker-compose.yml
services:
  postgres:
    image: postgres:16-alpine
    container_name: keycloak-postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: keycloak
      POSTGRES_USER: keycloak
      POSTGRES_PASSWORD: CHANGE_ME_STRONG_PWD
    volumes:
      - /opt/keycloak/data/postgres:/var/lib/postgresql/data

  keycloak:
    image: quay.io/keycloak/keycloak:26.0
    container_name: keycloak
    restart: unless-stopped
    depends_on:
      - postgres
    environment:
      KC_DB: postgres
      KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
      KC_DB_USERNAME: keycloak
      KC_DB_PASSWORD: CHANGE_ME_STRONG_PWD
      KC_HOSTNAME: auth.exemple.io
      KC_HOSTNAME_STRICT: "true"
      KC_HTTP_ENABLED: "true"
      KC_PROXY_HEADERS: xforwarded
      KEYCLOAK_ADMIN: admin
      KEYCLOAK_ADMIN_PASSWORD: CHANGE_ME_INITIAL_ADMIN
    command: start
    ports:
      - "127.0.0.1:8080:8080"
# Démarrer
cd /opt/keycloak
docker compose up -d

# Suivre le démarrage initial (30-60 secondes)
docker compose logs -f keycloak
# Attendre la ligne : Running the server in production mode

Keycloak écoute en HTTP sur 127.0.0.1:8080 — il ne doit jamais être exposé directement sur Internet en HTTP. On place un reverse-proxy TLS (Nginx, Caddy ou Traefik) devant qui termine TLS 1.3 et transmet via X-Forwarded-Proto. Configuration Caddy minimale qui automatise Let’s Encrypt :

# /etc/caddy/Caddyfile
auth.exemple.io {
    reverse_proxy 127.0.0.1:8080
    encode gzip
    header {
        Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        Referrer-Policy "no-referrer"
    }
}

Connexion à la console admin sur https://auth.exemple.io/admin avec les identifiants admin / CHANGE_ME_INITIAL_ADMIN. Première action obligatoire : changer ce mot de passe par un mot fort, créer un second compte administrateur nominatif, et supprimer ou désactiver le compte admin initial une fois la transition vérifiée.

Étape 3 — Créer un realm dédié et des utilisateurs

Un realm Keycloak est un domaine d’authentification isolé : ses utilisateurs, clients, rôles et configurations sont indépendants. La règle d’hygiène : ne jamais utiliser le realm master (réservé à l’administration de Keycloak lui-même) pour les utilisateurs métier. On crée un realm dédié.

Dans la console admin : Realms → Create realm. Nommer par exemple corp. Activer immédiatement les paramètres de sécurité :

  • Realm settings → Login → User registration : Off (sauf cas explicite d’inscription publique).
  • Realm settings → Login → Forgot password : On.
  • Realm settings → Login → Remember Me : Off pour des environnements sensibles.
  • Realm settings → Login → SSL required : External requests (production) ou All requests (paranoïaque).
  • Realm settings → Tokens → Access Token Lifespan : 5 minutes (suffisant, force le refresh).
  • Realm settings → Tokens → Refresh Token Max Reuse : 0 (rotation systématique).
  • Realm settings → Sessions → SSO Session Idle : 30 minutes ; SSO Session Max : 10 heures.

Création d’un utilisateur de test : Users → Add user, renseigner email, nom, prénom, marquer Email verified. Puis onglet Credentials → Set password (mot de passe initial, marqué Temporary pour forcer le changement à la première connexion).

Étape 4 — Activer la MFA : TOTP puis WebAuthn/FIDO2 (passkeys)

La MFA s’active dans Keycloak au niveau du flow d’authentification. Pour rendre TOTP obligatoire pour tous les utilisateurs du realm :

  • Authentication → Required actions : activer Configure OTP et marquer Set as default action. Tout utilisateur qui se connecte sans avoir configuré son TOTP sera contraint de le faire au premier login.
  • Authentication → Flows → Browser → OTP Form : passer en mode Required (au lieu de Alternative qui laisse l’utilisateur passer outre).

L’utilisateur scanne le QR code affiché par Keycloak avec une application TOTP (Aegis sur Android, 2FAS sur iOS, KeePassXC sur desktop — éviter Google Authenticator qui sauvegarde dans le cloud sans chiffrement de bout en bout opt-in clair). TOTP est conforme à RFC 6238 avec une fenêtre de 30 secondes et 6 chiffres par défaut.

TOTP est correct mais reste vulnérable au phishing par proxy (Evilginx, Modlishka) : l’attaquant proxifie la page de login Keycloak, l’utilisateur saisit son code à 6 chiffres sur le site de l’attaquant, qui le rejoue en temps réel. La vraie défense contre le phishing est WebAuthn / FIDO2 / passkeys — ces protocoles incluent l’origine du site dans la signature cryptographique, rendant l’attaque par proxy mathématiquement impossible. Le NIST SP 800-63B Rev. 4 (final juillet 2025, second draft public août 2024) classe les passkeys synchronisés comme AAL2 et les authentificateurs FIDO2 matériels (YubiKey, Feitian, Token2) comme AAL3, le plus haut niveau d’assurance.

Activation dans Keycloak :

  • Authentication → Required actions : activer Webauthn Register ou Webauthn Register Passwordless selon l’usage (second facteur ou passwordless complet).
  • Authentication → Policies → WebAuthn Policy : configurer User Verification = required, Authenticator Attachment = cross-platform (pour YubiKey USB) ou platform (pour Touch ID, Windows Hello), Attestation Conveyance Preference = direct.
  • Authentication → Flows → Browser → WebAuthn Authenticator : ajouter et placer en alternative à OTP (l’utilisateur choisit son second facteur le plus fort disponible).

Pour les comptes administrateurs et tous les comptes à privilèges, passer en mode WebAuthn obligatoire avec YubiKey ou équivalent matériel. Le surcoût de 50 € par administrateur est négligeable face au risque d’une compromission d’un compte privilégié.

Étape 5 — Intégrer une application web par Authorization Code + PKCE

On crée un client OIDC dans Keycloak puis on intègre une application Node.js d’exemple. Dans la console admin du realm corp :

  1. Clients → Create client. Client type = OpenID Connect, Client ID = webapp-portal.
  2. Capability config : Client authentication = On (confidential client), Authorization = Off (sauf si on utilise les UMA policies), Standard flow = On (Authorization Code), Direct access grants = Off (banni en OAuth 2.1), Service accounts roles = Off.
  3. Login settings : Root URL = https://portal.exemple.io, Valid redirect URIs = https://portal.exemple.io/auth/callback/*, Web origins = https://portal.exemple.io (jamais *).
  4. Onglet Credentials : copier le Client Secret (générer un secret aléatoire long via Regenerate Secret).

Côté application Node.js, exemple avec la bibliothèque officielle openid-client :

// app.js — Express + openid-client v6
import express from 'express';
import session from 'express-session';
import * as oidc from 'openid-client';

const app = express();
app.use(session({
  secret: process.env.SESSION_SECRET,
  resave: false,
  saveUninitialized: false,
  cookie: { secure: true, httpOnly: true, sameSite: 'lax' }
}));

const config = await oidc.discovery(
  new URL('https://auth.exemple.io/realms/corp'),
  process.env.OIDC_CLIENT_ID,
  process.env.OIDC_CLIENT_SECRET
);

app.get('/login', async (req, res) => {
  const codeVerifier = oidc.randomPKCECodeVerifier();
  const codeChallenge = await oidc.calculatePKCECodeChallenge(codeVerifier);
  const state = oidc.randomState();

  req.session.codeVerifier = codeVerifier;
  req.session.state = state;

  const authUrl = oidc.buildAuthorizationUrl(config, {
    redirect_uri: 'https://portal.exemple.io/auth/callback',
    scope: 'openid profile email',
    code_challenge: codeChallenge,
    code_challenge_method: 'S256',
    state
  });

  res.redirect(authUrl.href);
});

app.get('/auth/callback', async (req, res) => {
  const tokens = await oidc.authorizationCodeGrant(
    config,
    new URL(req.url, 'https://portal.exemple.io'),
    { pkceCodeVerifier: req.session.codeVerifier, expectedState: req.session.state }
  );
  const claims = tokens.claims();
  req.session.user = { sub: claims.sub, email: claims.email, name: claims.name };
  res.redirect('/');
});

Le flow Authorization Code + PKCE est le seul recommandé en 2026. Le code_challenge dérivé du code_verifier en SHA-256 protège contre l’interception du code d’autorisation. Le paramètre state protège contre les attaques CSRF. Les jetons sont stockés côté serveur (en session) — jamais dans le localStorage du navigateur.

Étape 6 — Fédération LDAP / Active Directory

La plupart des organisations disposent déjà d’un annuaire LDAP (OpenLDAP, FreeIPA) ou Active Directory. Plutôt que de dupliquer les utilisateurs dans Keycloak, on fédère : Keycloak interroge l’annuaire pour authentifier, et synchronise les attributs utilisateurs vers sa base. Configuration : User federation → Add Ldap providers.

Paramètres clés pour une fédération Active Directory en lecture seule :

  • Vendor : Active Directory.
  • UI display name : ad-corp.
  • Connection URL : ldaps://dc01.corp.exemple.io:636 (LDAPS obligatoire — TLS sur LDAP).
  • Bind type : simple, avec un compte de service AD dédié et droits de lecture uniquement.
  • Bind DN : CN=svc-keycloak,OU=ServiceAccounts,DC=corp,DC=exemple,DC=io.
  • Users DN : OU=Users,DC=corp,DC=exemple,DC=io.
  • Edit mode : READ_ONLY (les utilisateurs sont gérés dans AD, pas modifiables depuis Keycloak).
  • Sync settings : Periodic full sync toutes les 24h, Periodic changed users sync toutes les heures.

Tester la connexion avec le bouton Test connection et Test authentication. Puis synchroniser les utilisateurs : bouton Synchronize all users. Les utilisateurs AD apparaissent désormais dans Users avec un drapeau Federation Link indiquant leur origine.

Étape 7 — Audit, sauvegardes et durcissement Keycloak

Activation des journaux d’audit Keycloak (qui enrichissent kc.log et peuvent être exportés vers un SIEM via le module Event Listener) :

  • Realm settings → Events → Login Events : Save events On, Saved Types = tous, Event Listeners = jboss-logging.
  • Realm settings → Events → Admin Events : Save events On (toute action admin est tracée — création de client, modification de role, suppression d’utilisateur).

Pour exporter les événements en temps réel vers un SIEM : utiliser l’extension keycloak-event-listener-syslog (open-source) ou keycloak-metrics-spi (Prometheus metrics) selon la cible.

Sauvegardes : la base PostgreSQL est la seule source de vérité (la configuration, les utilisateurs locaux, les clients sont stockés en base). Backup quotidien automatisé :

# /etc/cron.daily/keycloak-backup
#!/bin/bash
set -e
TS=$(date +%Y%m%d-%H%M)
BACKUP_DIR=/opt/keycloak/backups
mkdir -p $BACKUP_DIR

docker exec keycloak-postgres pg_dump -U keycloak -d keycloak --no-owner --clean | gzip > $BACKUP_DIR/keycloak-$TS.sql.gz

# Rotation : 30 jours
find $BACKUP_DIR -name 'keycloak-*.sql.gz' -mtime +30 -delete

La restauration doit être testée trimestriellement sur un environnement de pré-production — sans test de restauration documenté, une sauvegarde est un acte de foi.

Erreurs fréquentes à éviter

Erreur Conséquence Bonne pratique
Utiliser le flow Implicit ou ROPC Tokens exposés dans l’URL, mot de passe transitant par le client Authorization Code + PKCE exclusivement
Stocker les tokens dans localStorage XSS = exfiltration de session triviale HttpOnly cookies côté serveur (BFF pattern)
Valid redirect URIs en * Vol de tokens via redirection malicieuse URIs exactes, jamais de wildcard de domaine
Garder le compte admin initial après mise en service Compte connu publiquement, cible de brute force Créer comptes nominatifs, désactiver le compte admin par défaut
MFA en mode Alternative au lieu de Required L’utilisateur peut éviter MFA Required dans le flow, configuration forcée par Required Actions
LDAP non-LDAPS Identifiants en clair sur le réseau interne LDAPS sur 636 obligatoire, certificat valide
Pas de monitoring des événements admin Modification non autorisée du fournisseur d’identité non détectée Export systématique vers SIEM, alertes sur création de client confidentiel

Tutoriels complémentaires

Questions fréquentes (FAQ)

Q : Keycloak ou Authentik ou Zitadel ?
R : Les trois sont des fournisseurs d’identité open-source crédibles. Keycloak (Red Hat) est le plus mature, le mieux documenté, soutenu par la fondation CNCF (Cloud Native Computing Foundation), et bénéficie d’une communauté importante — c’est le choix par défaut pour la majorité des cas. Authentik est plus moderne dans son UX et l’écosystème, écrit en Python, avec une intégration applicative plus directe. Zitadel est plus récent, cloud-native dès sa conception, en Go. Le critère décisif est l’écosystème d’extensions et la familiarité de l’équipe.

Q : Faut-il un cluster Keycloak en haute disponibilité ?
R : Pour la production, oui — au minimum deux instances Keycloak derrière un load balancer, partageant la base PostgreSQL et un cache distribué Infinispan. Keycloak 26 facilite considérablement le déploiement multi-site (Multi-Site Active/Passive) documenté officiellement, avec failover automatisé en cas de défaillance d’un datacenter.

Q : Comment migrer depuis ADFS ou un fournisseur SAML existant ?
R : Keycloak supporte SAML 2.0 nativement en tant que fournisseur ET consommateur. La stratégie de migration : configurer Keycloak comme fournisseur SAML pour les applications existantes (compatibilité immédiate, aucun changement applicatif), puis migrer progressivement les applications vers OIDC qui offre une expérience développeur supérieure. Keycloak peut aussi déléguer l’authentification à un fournisseur SAML existant (Identity Provider Federation) pendant la phase de transition.

Q : Passwordless complet en 2026 ?
R : Techniquement faisable et recommandé pour les déploiements nouveaux avec une population utilisateur disposant d’appareils compatibles (Touch ID, Windows Hello, Android avec écran d’empreinte, YubiKey). En pratique, le passwordless 100 % se déploie en plusieurs phases : passwordless optionnel pendant 6 mois, puis passwordless par défaut avec mot de passe en fallback, puis suppression du mot de passe. Les comptes de service et certaines intégrations héritées (LDAP bind) imposent encore le maintien d’un mot de passe.

Références et ressources officielles

Sponsoriser ce contenu

Cet emplacement est à vous

Position premium en fin d'article — c'est l'instant où les lecteurs sont le plus engagés. Réservez cet espace pour votre marque, votre formation ou votre offre.

Recevoir nos tarifs
Publicité