Aller au contenu principal

Ressources

Sécurité Keycloak : vingt points de configuration à vérifier et à corriger

Keycloak MFA, console d'administration, compte d'amorçage, clients, jetons, secrets et événements : vingt points de sécurité à vérifier en lecture seule.

Par , publié le · 28 min de lecture

Base d'expérience : Méthode et documentation officielle de Keycloak (guides serveur, guide d'administration et code au tag 26.7.4, comparés au tag 26.8.0 ; notes de version 26.7.1, 26.7.4, 26.7.5 et 26.8.0 ; guide de mise à niveau 26.8.0) et de Kubernetes ; motif d'élévation construit comme configuration type à partir de ces documentations.

Relecture factuelle : Claude Code (revue indépendante déléguée par Corentin Mas, 28/09/2026), le

Un Keycloak qui fonctionne n'est pas pour autant un Keycloak sûr. Les applications se connectent, et pourtant la console d'administration peut répondre depuis Internet, le compte d'amorçage servir encore, un client public accepter n'importe quelle URL de redirection et aucun événement d'administration quitter le serveur. Aucun de ces écarts n'exige une faille du produit : une valeur par défaut conservée, un raccourci de mise en service ou un droit délégué jamais relu suffisent.

Cet article passe en revue vingt points de configuration. Pour chacun : le risque, la vérification (kcadm.sh, l'outil en ligne de commande d'administration, l'API d'administration ou la console) et la correction, puis une grille d'autocontrôle et un relevé en lecture seule.

Faits datés

Cette lecture est établie sur Keycloak 26.7.4, publié le 16 septembre 2026, et relue le au regard des deux versions publiées depuis : 26.7.5, le 30 septembre 2026, et 26.8.0, le 1er octobre 2026, dernière version disponible au . Les guides, le code et les notes de version cités ont été vérifiés à cette date dans les dépôts officiels ; les changements apportés par 26.8.0 sont signalés point par point.

Vérifié le

Comptes d'administration et royaume master

Selon la documentation, le royaume master sert uniquement à créer et gérer les autres royaumes. Un utilisateur qui y porte le rôle admin est un super-utilisateur qui gère tous les royaumes du serveur, et chaque royaume y est représenté par un client nommé <royaume>-realm dont les rôles délèguent son administration. Tout ce qui touche à ce royaume touche donc à l'ensemble.

Console et royaume master joignables depuis Internet

Risque. Une console exposée offre un formulaire de connexion vers le compte le plus puissant du serveur, protégé par le seul mot de passe. Le guide du proxy inverse classe /admin/ et /realms/master/ en « exposition interne uniquement » ; /, /metrics et /health ne doivent pas être exposés du tout. Seuls /realms/, /resources/, /.well-known/ et, s'il est activé, /lb-check ont vocation à être publics.

Vérifier. Depuis un réseau externe, sans authentification : curl -s -o /dev/null -w '%{http_code}\n' https://<hôte-public>/admin/master/console/ puis la même requête sur /realms/master/.well-known/openid-configuration. Une réponse 200 sur l'un ou l'autre est un constat.

Corriger. Filtrer au niveau du proxy inverse. L'option hostname-admin publie la console sur un nom d'hôte distinct, mais la documentation précise qu'elle n'empêche pas d'atteindre l'API REST d'administration par l'URL publique : la restriction se fait au proxy, pas dans Keycloak.

Compte d'amorçage temporaire encore actif

Risque. Les options --bootstrap-admin-username et --bootstrap-admin-password (ou leurs variantes client pour un compte de service) créent un compte que la documentation qualifie de temporaire : il doit exister le temps d'obtenir un accès administrateur permanent et plus sûr, puis être supprimé à la main. Laissé en place, il devient un identifiant partagé, qui peut se retrouver dans un fichier de valeurs ou une variable d'environnement.

Le piège. Ce compte n'est créé qu'au tout premier démarrage, lorsque le royaume master n'existe pas encore. Retirer ou changer la variable ensuite ne modifie rien dans la base : le compte et son mot de passe restent valides. Il en allait de même avec KEYCLOAK_ADMIN et KEYCLOAK_ADMIN_PASSWORD, lues au premier démarrage seulement et dépréciées depuis la version 26 au profit de KC_BOOTSTRAP_ADMIN_USERNAME et KC_BOOTSTRAP_ADMIN_PASSWORD.

Vérifier. Console : royaume master, Users, repérer les comptes non nominatifs ; la console signale le compte temporaire. En ligne de commande : kcadm.sh get users -r master --fields username,enabled,createdTimestamp.

Corriger. Créer des administrateurs nominatifs, leur imposer un second facteur, puis supprimer le compte d'amorçage. En cas de perte d'accès, la commande kc.sh bootstrap-admin user (ou service) recrée un accès de secours (tous les nœuds arrêtés au préalable), avec --password:env pour lire le secret dans l'environnement.

Administrateurs sans second facteur

Risque. Un mot de passe réutilisé ou hameçonné donne le contrôle de tous les royaumes.

Vérifier. Pour chaque administrateur du royaume master : kcadm.sh get users/<id>/credentials -r master ; l'absence d'un identifiant de type otp ou webauthn est un constat. Vérifier aussi que le flux de navigation du royaume master exige ce facteur, et pas seulement qu'il le propose.

Corriger. Rendre le second facteur obligatoire dans le flux d'authentification du royaume master, ou déléguer l'authentification des administrateurs à un fournisseur d'identité qui l'impose déjà. Prévoir un compte de secours documenté, hors usage courant.

Applications déclarées dans le royaume master

Risque. Une application cliente du royaume master partage le formulaire, les politiques et les sessions des super-administrateurs. Une erreur de configuration sur ce client, ou un utilisateur applicatif créé dans ce royaume, rapproche un compte ordinaire des droits globaux. La documentation déconseille d'ailleurs d'y créer des utilisateurs.

Vérifier. kcadm.sh get clients -r master --fields clientId : au-delà des clients fournis par Keycloak et des clients <royaume>-realm, tout client applicatif est un constat.

Corriger. Déplacer applications et utilisateurs vers un royaume dédié, réserver master à l'administration.

Détection de force brute désactivée

Risque. La documentation l'indique, et le code des versions 26.7.4 et 26.8.0 le confirme : un royaume est créé avec la détection de force brute désactivée. Une fois activée, les valeurs par défaut sont larges : 30 échecs avant verrouillage, incrément d'attente d'une minute, attente maximale de 15 minutes, remise à zéro après 12 heures.

Vérifier. kcadm.sh get realms/<royaume> --fields bruteForceProtected,permanentLockout,failureFactor,waitIncrementSeconds,maxFailureWaitSeconds, pour chaque royaume, master compris.

Corriger. Activer la détection et choisir un mode de verrouillage temporaire. La documentation rappelle que le verrouillage permet aussi à un attaquant de bloquer des comptes connus : un verrouillage permanent sans filtrage réseau en amont transforme la protection en déni de service. Depuis 26.8.0, les échecs de connexion sont conservés en base par défaut : un verrouillage temporaire survit au redémarrage complet du cluster, ce qui n'était pas le cas avec le stockage en mémoire des versions précédentes.

Droits délégués et chemins d'élévation

Déléguer l'administration est une bonne pratique, à condition de lire chaque rôle comme un chemin possible vers un rôle plus élevé. Keycloak protège explicitement l'attribution de rôles : un administrateur qui porte manage-users ne peut attribuer que les rôles d'administration qu'il détient lui-même. Cette protection couvre l'attribution directe, pas les chemins indirects décrits ci-dessous.

Comptes de service porteurs de realm-admin

Risque. Un client en client credentials dont le compte de service porte realm-admin concentre les droits complets du royaume dans un secret, qui peut être stocké hors de Keycloak et partagé entre outils. Quiconque lit ou régénère ce secret devient administrateur du royaume ; avant la version 26.8.0, le rôle view-clients suffit à le lire.

Vérifier. Pour chaque client dont serviceAccountsEnabled est vrai, lister les rôles effectifs de son compte, nommé service-account-<clientId> : kcadm.sh get-roles -r <royaume> --uusername service-account-<clientid> --cclientid realm-management --effective. La présence de realm-admin, manage-realm, manage-users ou manage-clients est un constat à justifier ligne par ligne.

Corriger. Réduire au rôle nécessaire (view-users, query-users, etc.) ou passer par les permissions d'administration à granularité fine. Traiter le secret de ces clients comme un identifiant d'administrateur : rotation, stockage dans un coffre, périmètre d'accès documenté.

Permissions à granularité fine (FGAP v2) trop larges

Dans la branche 26.7, la version 2 des permissions d'administration à granularité fine (FGAP, fine-grained admin permissions) est la version supportée ; la version 1, dépréciée, ne s'active plus que par --features=admin-fine-grained-authz:v1. La version 2 s'active par royaume (Realm settings, Admin Permissions) et crée un client admin-permissions qui porte les politiques.

Risque. Trois portées ouvrent un chemin vers les droits d'un autre compte :

  • reset-password sur les utilisateurs : faute de permission dédiée, Keycloak retombe sur la portée manage. Une permission « gérer tous les utilisateurs » donnée au support permet donc aussi de réinitialiser le mot de passe d'un administrateur inclus dans le périmètre.
  • impersonate, qui permet d'agir sous l'identité d'un autre utilisateur.
  • manage-membership sur un groupe, qui permet d'y ajouter des membres, donc de leur en donner les rôles, et les droits que d'autres systèmes accordent à ce groupe lorsqu'il est projeté dans les jetons.

Les rôles admin et realm-admin court-circuitent entièrement ce modèle : la documentation demande de relire les comptes qui les portent pour éviter toute élévation de privilèges.

Vérifier. Console : Permissions du royaume, relire chaque permission portant sur « tous les utilisateurs » ou « tous les groupes », et contrôler que les administrateurs sont exclus des permissions manage, reset-password et impersonate données au support.

Corriger. Restreindre le périmètre à des groupes identifiés, en sortir les administrateurs, et accorder reset-password explicitement plutôt que par manage.

Rôle d'usurpation d'identité

Le rôle impersonation du client realm-management mérite un traitement à part : Keycloak 26.7.4 corrige la CVE-2026-17526, par laquelle un porteur de ce rôle pouvait usurper l'identité d'un administrateur du royaume. Sur un serveur non corrigé, ce rôle se relit donc comme un rôle d'administration ; la vérification de version est traitée au quatrième chapitre.

Un motif d'élévation qui traverse la plateforme

Les points précédents peuvent se combiner. Le motif suivant est une configuration type, décrite sans aucun détail d'environnement : aucun de ses maillons n'est une faille de Keycloak ni de Kubernetes, et chacun peut exister isolément.

Un motif d'élévation qui traverse la plateforme

Six maillons de configuration, chacun banal isolément, conduisent d'un compte Kubernetes en lecture seule aux droits d'administration du cluster.

Schéma défilable horizontalement ; sa version textuelle complète suit.

Lire le schéma sous forme textuelle
  1. Un compte Kubernetes est déclaré « en lecture seule » : son rôle refuse la lecture des Secrets, mais autorise la lecture des charges de travail.
  2. Le mot de passe du compte d'amorçage de Keycloak, chiffré dans le dépôt, est déchiffré au rendu du chart et injecté comme variable d'environnement littérale : il figure en clair dans la spécification de la charge de travail, que ce compte peut lire.
  3. La console d'administration et le royaume master sont joignables depuis Internet.
  4. Le compte d'amorçage, jamais supprimé, ouvre une session d'administrateur global, donc l'accès à tous les royaumes.
  5. Un groupe Keycloak est projeté dans le claim de groupes des jetons, et le cluster lie ce groupe à des droits d'administration étendus.
  6. L'administrateur Keycloak peut s'ajouter à ce groupe : il obtient des droits d'administration du cluster, à partir d'un compte censé ne rien pouvoir modifier.
Modèle explicatif : chaque maillon est décrit dans les guides Keycloak et la documentation Kubernetes cités en fin d'article.

Trois enseignements s'en dégagent. Refuser la lecture des Secrets ne protège rien si les secrets sont recopiés en valeur littérale dans des objets lisibles : une variable d'environnement peut référencer un Secret (valueFrom.secretKeyRef) au lieu de porter la valeur. Le fournisseur d'identité fait partie de la base de confiance de tout système qui consomme ses groupes : administrer le royaume revient à administrer ces systèmes. Enfin, l'ordre de correction compte : changer le mot de passe dans Keycloak ou supprimer le compte (changer la variable ne révoque rien), créer des administrateurs nominatifs avec second facteur, ne fournir KC_BOOTSTRAP_ADMIN_USERNAME et KC_BOOTSTRAP_ADMIN_PASSWORD que depuis un Secret, restreindre /admin/ et /realms/master/ au proxy, activer les événements d'administration.

Clients, jetons et attributs

Les points liés aux clients se multiplient avec les applications : chaque client ajoute ses propres réglages. Le choix du protocole lui-même est traité dans l'article « OIDC ou SAML : choisir le protocole et fédérer Keycloak avec Entra ID ».

Flux implicite et accès direct laissés actifs

Risque. Le flux implicite livre les jetons dans l'URL de retour, avec un risque de fuite par l'historique du navigateur ; la documentation déconseille de l'utiliser. L'accès direct (Direct access grants, octroi par mot de passe du propriétaire de la ressource) fait transiter le mot de passe de l'utilisateur par l'application et suit son propre flux d'authentification, direct grant : une exigence ajoutée au seul flux de navigation ne s'y applique pas. Les deux profils OAuth 2.1 intégrés à Keycloak rejettent l'un et l'autre.

Vérifier. kcadm.sh get clients -r <royaume> --fields clientId,implicitFlowEnabled,directAccessGrantsEnabled ; toute valeur vraie doit être justifiée par un besoin encore actif.

Corriger. Désactiver les deux sur les clients qui utilisent le flux d'autorisation standard. Pour l'imposer au royaume, créer une politique de client appliquant les exécuteurs reject-implicit-grant et reject-ropc-grant, fournis par les profils OAuth 2.1 intégrés.

Clients publics sans PKCE

Risque. Selon la documentation, PKCE (Proof Key for Code Exchange) empêche un attaquant qui a volé un code d'autorisation d'obtenir les jetons. Laissé vide, le réglage PKCE Method ne fait appliquer PKCE que si le client l'envoie de lui-même.

Vérifier. Pour chaque client public, lire l'attribut pkce.code.challenge.method ; une valeur absente ou plain est un constat.

Corriger. Fixer S256 client par client, ou créer une politique de client qui applique le profil oauth-2-1-for-public-client. Ce profil ajoute aussi un exécuteur de liaison DPoP (dpop-bind-enforcer) : à tester sur une application avant de l'étendre à tout le royaume.

URL de redirection et origines génériques

Risque. Une URL de redirection trop large permet de détourner un code d'autorisation vers une page contrôlée par un tiers. La documentation demande des URL aussi précises que possible et déconseille le joker complet * en production ; elle rappelle qu'une redirection vague permet à un client malveillant d'usurper un autre client, par exemple lorsque les deux partagent le même domaine. Les origines web (Web origins) gouvernent le CORS (partage de ressources entre origines) et sont inscrites dans le jeton d'accès.

Vérifier. kcadm.sh get clients -r <royaume> --fields clientId,redirectUris,webOrigins, puis rechercher *, les jokers placés avant la fin du chemin, les schémas http:// hors boucle locale et les domaines génériques.

Corriger. Énumérer les URL exactes. Pour empêcher le retour du problème, appliquer l'exécuteur secure-redirect-uris-enforcer par une politique de client.

Portée complète et rôles dans les jetons

Risque. Full scope allowed est actif par défaut sur un nouveau client qui n'exige pas de consentement : le client reçoit alors dans ses jetons tous les rôles de l'utilisateur, y compris ceux d'autres applications. Un jeton fuité ou rejoué ailleurs porte plus de droits que nécessaire. Depuis la version 26.8.0, ce réglage est déprécié et sera retiré dans une version future ; le serveur journalise un avertissement de niveau WARN à chaque émission de jeton pour un client qui le conserve, sauf pour les clients intégrés security-admin-console et admin-cli.

Vérifier. kcadm.sh get clients -r <royaume> --fields clientId,fullScopeAllowed ; les clients intégrés security-admin-console et admin-cli l'ont activé par construction et ne sont pas un constat. Sur 26.8.0, les avertissements du journal désignent les autres clients concernés.

Corriger. Désactiver Full scope allowed sur les clients applicatifs (onglet Client scopes, portée dédiée du client, onglet Scope), n'y déclarer que les rôles utiles et contrôler le jeton obtenu avec l'outil Evaluate des portées de client. Ne pas le désactiver à la main sur security-admin-console ni sur admin-cli : la documentation de la version 26.8.0 prévient que cela peut empêcher immédiatement la connexion à la console d'administration. Sur 26.8.0, l'exécuteur full-scope-disabled, appliqué par une politique de client, désactive le réglage sur tout client créé ou modifié ; il faut alors en exclure ces deux clients intégrés, comme le décrit la documentation.

Attributs modifiables par l'utilisateur utilisés pour autoriser

Risque. Une application décide d'un droit à partir d'un attribut d'utilisateur copié dans le jeton (département, niveau, locataire), alors que l'utilisateur peut modifier cet attribut depuis la console de compte. Il s'accorde alors lui-même le droit. Le profil utilisateur déclaratif fixe, attribut par attribut, qui peut modifier la valeur (permissions.edit, avec user ou admin) ; les attributs non déclarés restent inaccessibles à l'utilisateur tant que la politique unmanagedAttributePolicy ne vaut pas ENABLED.

Vérifier. Croiser deux lectures : kcadm.sh get users/profile -r <royaume>, pour repérer les attributs dont permissions.edit inclut user et la valeur de unmanagedAttributePolicy ; et les mappeurs de protocole des clients et des portées qui copient un attribut d'utilisateur dans les jetons. Un attribut présent dans les deux listes et utilisé pour autoriser est un constat.

Corriger. Réserver l'édition de ces attributs aux administrateurs, ou porter l'information par un rôle ou un groupe. Côté application, n'autoriser que sur des claims dont l'origine est maîtrisée.

Durées de vie et jetons de rafraîchissement

Risque. Les valeurs par défaut, identiques en 26.7.4 et en 26.8.0, sont mesurées : jeton d'accès de 5 minutes, session inactive de 30 minutes, session maximale de 10 heures, session hors ligne inactive de 30 jours. Le risque vient des valeurs allongées « pour éviter les déconnexions », par exemple par une surcharge sur un seul client. Autre point : Revoke Refresh Token est désactivé par défaut ; un jeton de rafraîchissement déjà utilisé n'est pas invalidé et reste utilisable jusqu'à son expiration.

Vérifier. kcadm.sh get realms/<royaume> --fields accessTokenLifespan,ssoSessionIdleTimeout,ssoSessionMaxLifespan,offlineSessionIdleTimeout,revokeRefreshToken,refreshTokenMaxReuse, puis les surcharges dans les attributs de chaque client.

Corriger. Garder le jeton d'accès court, justifier chaque surcharge, activer Revoke Refresh Token avec une réutilisation nulle pour les clients publics, et limiter l'usage des sessions hors ligne. En cas de compromission, la documentation prévoit de pousser une politique not-before et de fermer toutes les sessions.

Fournisseurs d'identité inutilisés ou trop confiants

Risque. Un fournisseur d'identité ajouté pour un essai reste actif et visible sur le formulaire de connexion. Plus grave : un flux de première connexion personnalisé qui rattache un compte local existant sans vérification (authentificateur Automatically Set Existing User). La documentation qualifie cette liaison automatique de faille potentielle et juge l'authentificateur dangereux dès que les utilisateurs choisissent librement leur nom ou leur adresse. Trust Email dispense en outre de vérifier l'adresse reçue du fournisseur.

Vérifier. kcadm.sh get identity-provider/instances -r <royaume> --fields alias,enabled,trustEmail,firstBrokerLoginFlowAlias,linkOnly, puis relire dans Authentication le flux nommé par firstBrokerLoginFlowAlias.

Corriger. Supprimer ce qui ne sert pas, ne déclarer l'e-mail fiable que pour un fournisseur qui le vérifie, et garder la confirmation de liaison du flux par défaut.

Secrets, transport, version et traçabilité

Une partie des points ne se lit pas dans la console : ils se trouvent dans le chart, les manifestes, le proxy et le pipeline de journaux.

Secrets en clair dans les manifestes et les exports

Risque. Mot de passe de base, secret d'amorçage, secret de client ou mot de passe SMTP apparaissent en clair dans un fichier de valeurs, une variable d'environnement littérale ou un export de royaume versionné.

Vérifier. Chercher les variables d'environnement littérales aux noms sensibles dans les charges de travail, sans afficher les valeurs :

kubectl get deployments,statefulsets -A -o json | jq -r '
  .items[]
  | (.kind + " " + .metadata.namespace + "/" + .metadata.name) as $w
  | (.spec.template.spec.containers + (.spec.template.spec.initContainers // []))[]
  | .env[]?
  | select(.value != null and (.name | test("PASS|SECRET|TOKEN|KEY"; "i")))
  | "\($w) \(.name)"'

Corriger. Référencer des Secrets Kubernetes plutôt que des valeurs. Pour les secrets consommés par Keycloak lui-même (SMTP, fournisseur d'identité, LDAP), utiliser le coffre intégré et des références ${vault.<clé>}, comme le détaille l'article « Piloter la configuration Keycloak en GitOps : adoption, dérive et suppression de champs ».

Transport non chiffré et mode SSL par défaut

Risque. Le mode SSL d'un royaume vaut external à la création : les requêtes venant d'adresses privées (localhost, 10.x.x.x, 172.16.x.x, 192.168.x.x) sont acceptées sans TLS. Derrière un proxy qui termine TLS, le trafic entre le proxy et Keycloak, et entre Keycloak et sa base, peut circuler en clair sur le réseau interne.

Vérifier. kcadm.sh get realms/<royaume> --fields sslRequired ; relire la chaîne de connexion de la base et la configuration HTTPS du serveur.

Corriger. Chiffrer le lien du proxy vers Keycloak et le lien vers la base, puis passer le royaume en all lorsque tout le trafic arrive en HTTPS.

Proxy et nom d'hôte mal réglés

Risque. Le guide du proxy inverse prévient qu'une mauvaise configuration de proxy-headers expose Keycloak : si le proxy ajoute des en-têtes au lieu de les écraser, un client peut falsifier son adresse ou le schéma perçu. Une adresse falsifiée fausse les journaux et peut faire passer une requête externe pour une requête privée au regard du mode SSL external.

Vérifier. Relire proxy-headers (forwarded ou xforwarded), proxy-trusted-addresses et les options de nom d'hôte : avec hostname-strict à false et sans hostname, les URL sont résolues dynamiquement à partir de la requête, donc des en-têtes transmis par le proxy si proxy-headers est actif.

Corriger. Faire écraser les en-têtes par le proxy, déclarer ses adresses dans proxy-trusted-addresses et isoler le réseau entre proxy et serveur.

Le même réglage de proxy concerne les sondes de santé. Une sonde qui interroge la page d'accueil publique mesure le proxy, pas Keycloak. Les contrôles de santé et les métriques sont servis sur le port de management 9000, que le guide demande de ne pas exposer publiquement : les sondes Kubernetes visent /health/ready sur ce port, le répartiteur externe utilise /lb-check s'il est activé, et aucune route publique ne mène à /health ni à /metrics. Le détail des sondes est traité dans « Keycloak en haute disponibilité sur Kubernetes : caches, sessions, tests de panne et restauration ».

Version en retard sur les correctifs de sécurité

Risque. Les versions correctives de la branche 26.7 corrigent des élévations de privilèges : douze correctifs de sécurité en 26.7.1, publiée le 5 août 2026, dont deux contournements des permissions à granularité fine (CVE-2026-14614, CVE-2026-14615) et deux élévations par l'enregistrement dynamique de clients (CVE-2026-15572, CVE-2026-16102) ; six en 26.7.4, dont celui du rôle d'usurpation ; quatorze en 26.7.5, publiée le 30 septembre 2026, dont la CVE-2026-89298, par laquelle un porteur de view-clients lisait en clair, par le point d'enregistrement des clients, le secret d'un client confidentiel. La version 26.8.0, publiée le 1er octobre 2026, corrige en outre la CVE-2026-12388 : un administrateur limité à la gestion des fournisseurs d'identité (manage-identity-providers) pouvait, par un mappeur, attribuer un rôle d'administration et élever ses propres droits. Au , ce correctif ne figure pas dans les notes de version de 26.7.5. Un serveur en 26.7.0 reste exposé à toutes ces failles publiées, un serveur en 26.7.4 à celles corrigées par 26.7.5 et 26.8.0.

Vérifier. kcadm.sh get serverinfo | jq -r '.systemInfo.version' ; le serveur ne renvoie la version qu'à un compte qui peut gérer le royaume (manage-realm), sinon lire l'étiquette de l'image du conteneur. Comparer ensuite avec les notes de version publiées sur GitHub.

Corriger. Suivre la dernière version corrective de la branche, et relire les notes de version de la branche suivante pour repérer les correctifs qui n'y sont pas reportés : au , la correction de la CVE-2026-12388 n'est publiée qu'en 26.8.0. Planifier les montées de branche : voir « Monter de version Keycloak sans casser la production : politique de support, migration de base et retour arrière ». Pour les extensions maison, voir « Extensions Keycloak en production : choisir le bon SPI, le livrer et survivre aux mises à jour ».

Événements non enregistrés ou invisibles pour le SIEM

Risque. Par défaut, Keycloak n'enregistre aucun événement, ni utilisateur ni d'administration. Le code des versions 26.7.4 et 26.8.0 ajoute une subtilité : les événements d'administration partent vers les écouteurs configurés même sans enregistrement, mais l'écouteur jboss-logging écrit les succès au niveau debug et les erreurs au niveau warn. Avec un niveau de journal info, une création d'administrateur ou un changement de client ne laisse aucune trace exploitable dans le SIEM (système de gestion des informations et des événements de sécurité).

Vérifier. kcadm.sh get events/config -r <royaume> : lire eventsEnabled, eventsListeners, adminEventsEnabled et adminEventsDetailsEnabled. Puis contrôler qu'une modification de test apparaît dans le SIEM.

Corriger. Activer l'enregistrement avec une durée d'expiration, activer les événements d'administration et, si les journaux alimentent le SIEM, relever le niveau de succès de l'écouteur : --spi-events-listener--jboss-logging--success-level=info. L'option Include representation conserve le document JSON envoyé, secrets retirés par le serveur ; son volume est à dimensionner.

Configuration faite à la main

Risque. Une configuration modifiée dans la console n'a ni revue, ni historique hors des événements d'administration, ni retour arrière. Les points précédents peuvent réapparaître après chaque correction manuelle.

Corriger. Décrire royaumes et clients dans un dépôt, appliquer par un compte de service dédié et limité, et traiter tout écart comme une dérive. La méthode est détaillée dans l'article GitOps cité plus haut.

Grille d'autocontrôle et relevé en lecture seule

La grille reprend les vingt points dans un ordre de gravité indicatif, du plus direct au plus diffus. Elle sert de liste de contrôle avant une mise en production ou lors d'une revue périodique. Pour intégrer ces vérifications aux critères d'ouverture d'une plateforme, voir la page Mise en production Kubernetes : ouvrir par étapes ; pour une revue ponctuelle de l'existant, la page Audit d'infrastructure cloud : savoir quoi corriger en premier décrit comment elle est cadrée.

Vingt points de configuration Keycloak, avec leur risque principal, leur vérification rapide et leur correction
#PointRisque principalVérification rapideCorrection
1/admin/ ou /realms/master/ publicsAttaque directe du compte le plus puissantcurl depuis l'extérieurFiltrage au proxy
2Compte d'amorçage temporaire actifIdentifiant partagé, jamais révoquéUtilisateurs du royaume masterAdministrateurs nominatifs, suppression
3Administrateurs sans second facteurPrise de contrôle par mot de passeusers/<id>/credentialsSecond facteur obligatoire
4Applications dans masterProximité avec les droits globauxClients du royaume masterRoyaume dédié
5Force brute désactivéeEssais de mots de passe illimitésbruteForceProtectedVerrouillage temporaire
6Compte de service avec realm-adminSecret équivalent à un administrateurget-roles --effectiveRôles minimaux, rotation
7Permissions FGAP largesRéinitialisation ou usurpation d'un administrateurPermissions du royaumePérimètre restreint
8Version antérieure à 26.7.5, sans les correctifs propres à 26.8.0Failles publiées, dont l'usurpation et l'élévation par mappeurserverinfo ou image du conteneurVersion corrective, montée vers 26.8
9Flux implicite ou accès directJeton exposé, exigence du flux de navigation contournéeChamps du clientDésactivation, politique
10Client public sans PKCEVol de code d'autorisationAttribut PKCES256 ou profil OAuth 2.1
11Redirections génériquesDétournement de coderedirectUris, webOriginsURL exactes, exécuteur
12Portée complète (réglage déprécié en 26.8.0)Jetons trop richesfullScopeAllowed, hors clients intégrésPortées déclarées, exécuteur full-scope-disabled en 26.8.0
13Attribut modifiable utilisé pour autoriserAuto-attribution de droitsProfil utilisateur et mappeursÉdition réservée
14Durées longues, pas de révocationJeton volé durablement utileChamps du royaumeRotation stricte
15Fournisseur d'identité inutile ou trop confiantLiaison de compte abusiveInstances de fournisseursSuppression, confirmation
16Secrets en clairFuite par simple lectureRecherche dans les chargesSecrets, coffre
17Transport interne en clairInterception internesslRequired, baseTLS de bout en bout
18En-têtes de proxy non maîtrisésAdresse et schéma falsifiésOptions de proxyÉcrasement, adresses de confiance
19Événements absents du SIEMAucune trace d'administrationevents/configEnregistrement et niveau info
20Configuration manuelleDérive, pas de retour arrièreÉvénements d'administrationDépôt et GitOps

Relevé en lecture seule avec kcadm.sh

Le relevé s'exécute avec un compte limité aux rôles view-realm, view-clients, view-users, view-events et view-identity-providers du royaume visé, jamais avec un administrateur global. Il ne modifie rien. Ce compte reste sensible : jusqu'à la branche 26.7 incluse, le rôle view-clients permet de lire en clair, par l'API d'administration, le secret de chaque client confidentiel, y compris celui d'un compte de service porteur de realm-admin ; depuis 26.8.0, ce secret est masqué pour un appelant qui n'a que view-clients. Sur une version antérieure, protéger ses identifiants comme ceux d'un administrateur et le désactiver après usage. Le relevé suppose jq et utilise un fichier de configuration temporaire (--config), supprimé à la fin, pour ne pas laisser de jeton dans ~/.keycloak/kcadm.config. Faute d'option --password, kcadm.sh demande le mot de passe, ou le lit dans KC_CLI_PASSWORD. Avec ce compte, la version n'est pas renvoyée : la lire sur l'image du conteneur.

#!/usr/bin/env bash
# Référence synthétique pour Keycloak 26.7.4 et 26.8.0 : relevé en lecture seule, à adapter
set -euo pipefail
KC_URL='https://<hôte-admin-interne>'
REALM='<royaume>'
CFG="$(mktemp)"; trap 'rm -f "$CFG"' EXIT
KCADM="kcadm.sh"

"$KCADM" config credentials --config "$CFG" --server "$KC_URL" \
  --realm "$REALM" --user '<compte-lecture-seule>'

echo "== Version (renvoyée seulement avec manage-realm)"
"$KCADM" get serverinfo --config "$CFG" | jq -r '.systemInfo.version // "non renvoyée"'

echo "== Royaume : force brute, SSL, jetons, événements"
"$KCADM" get "realms/$REALM" --config "$CFG" --fields \
realm,sslRequired,bruteForceProtected,failureFactor,permanentLockout,\
accessTokenLifespan,ssoSessionIdleTimeout,ssoSessionMaxLifespan,\
offlineSessionIdleTimeout,revokeRefreshToken,refreshTokenMaxReuse

"$KCADM" get events/config -r "$REALM" --config "$CFG"

echo "== Clients : flux, PKCE, redirections, portée complète"
"$KCADM" get clients -r "$REALM" --config "$CFG" | jq -r '.[]
  | select(.implicitFlowEnabled or .directAccessGrantsEnabled
      or (.publicClient and ((.attributes["pkce.code.challenge.method"] // "") != "S256"))
      or ((.redirectUris // []) | any(. == "*" or test("\\*.+/")))
      or .fullScopeAllowed)
  | [.clientId, "implicit=\(.implicitFlowEnabled)", "direct=\(.directAccessGrantsEnabled)",
     "public=\(.publicClient)", "pkce=\(.attributes["pkce.code.challenge.method"] // "-")",
     "fullScope=\(.fullScopeAllowed)"] | @tsv'

echo "== Comptes de service et rôles d'administration effectifs"
"$KCADM" get clients -r "$REALM" --config "$CFG" \
  | jq -r '.[] | select(.serviceAccountsEnabled) | .clientId' \
  | while read -r cid; do
      roles=$("$KCADM" get-roles -r "$REALM" --config "$CFG" \
        --uusername "service-account-${cid,,}" --cclientid realm-management --effective \
        | jq -r '[.[].name] | join(",")')
      if [ -n "$roles" ]; then echo "$cid : $roles"; fi
    done

echo "== Fournisseurs d'identité"
"$KCADM" get identity-provider/instances -r "$REALM" --config "$CFG" \
  --fields alias,enabled,trustEmail,linkOnly,firstBrokerLoginFlowAlias

Le résultat se lit avec la grille : chaque ligne affichée par le bloc des clients est un point à qualifier, sauf security-admin-console et admin-cli, qui conservent la portée complète par construction ; chaque rôle d'administration listé pour un compte de service doit être justifié. Le relevé ne couvre ni l'exposition réseau (point 1), ni les secrets des manifestes (point 16), ni le SIEM (point 19) : ces trois points se vérifient depuis l'extérieur et côté plateforme, avec les commandes données plus haut.

Ordre de correction

L'ordre suit la gravité : fermer l'exposition de /admin/ et /realms/master/, changer ou supprimer le compte d'amorçage, imposer le second facteur aux administrateurs, activer les événements d'administration, puis réduire les droits délégués et les comptes de service. Les clients et les jetons viennent ensuite, application par application, car chaque parcours de connexion doit être testé. La montée de version se mène en parallèle.

Sources officielles et limites de lecture

Les comportements décrits ont été vérifiés le dans les sources primaires listées ci-dessous : guides serveur, guide d'administration et code du dépôt Keycloak au tag 26.7.4, comparés au tag 26.8.0, notes de version 26.7.1, 26.7.4, 26.7.5 et 26.8.0 publiées sur GitHub, guide de mise à niveau de la version 26.8.0, guide de configuration au tag 25.0.6 pour l'ancien comportement de KEYCLOAK_ADMIN, documentation Kubernetes pour les références de Secrets.

Cette lecture a des limites. Elle porte sur la configuration et ne constitue pas une recherche de vulnérabilités. Elle ne dit rien d'une instance donnée : chaque valeur se relit sur le serveur déployé, avec ses extensions et ses politiques, et les commandes s'exécutent d'abord sur un environnement de test. Les valeurs par défaut citées valent pour un royaume créé en 26.7.4 et sont inchangées en 26.8.0 ; un royaume importé ou migré depuis une version antérieure conserve ses propres valeurs. Enfin, le choix de Keycloak lui-même face à un fournisseur d'identité managé est un autre sujet, traité dans « Keycloak, c'est quoi et quand le choisir (ou pas) face aux IdP managés et aux alternatives open source ».

Sources

  1. Release 26.7.4 (correctifs de sécurité, dont CVE-2026-17526), dépôt keycloak/keycloak, https://github.com/keycloak/keycloak/releases/tag/26.7.4, consulté le 07/10/2026.
  2. Release 26.7.1 (correctifs de sécurité), dépôt keycloak/keycloak, https://github.com/keycloak/keycloak/releases/tag/26.7.1, consulté le 07/10/2026.
  3. Bootstrapping and recovering an admin account, source au tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/guides/server/bootstrap-admin-recovery.adoc, consulté le 07/10/2026.
  4. Upgrading Guide, changements de la version 26.0.0, section Admin Bootstrapping and Recovery, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/upgrading/topics/changes/changes-26_0_0.adoc, consulté le 07/10/2026.
  5. Configuring Keycloak, création de l'administrateur initial, source au tag 25.0.6, https://github.com/keycloak/keycloak/blob/25.0.6/docs/guides/server/configuration.adoc, consulté le 07/10/2026.
  6. Configuring a reverse proxy, source au tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/guides/server/reverseproxy.adoc, consulté le 07/10/2026.
  7. Configuring the hostname (v2), source au tag 26.8.0, https://github.com/keycloak/keycloak/blob/26.8.0/docs/guides/server/hostname.adoc, consulté le 07/10/2026.
  8. The master realm (realms/master.adoc) et Creating a user (users/proc-creating-user.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/realms/master.adoc, consulté le 07/10/2026.
  9. Master realm access control (master-realm.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/admin-console-permissions/master-realm.adoc, consulté le 07/10/2026.
  10. Dedicated realm admin consoles (per-realm.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/admin-console-permissions/per-realm.adoc, consulté le 07/10/2026.
  11. Fine-grained admin permissions (fine-grain-v2.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/admin-console-permissions/fine-grain-v2.adoc, consulté le 07/10/2026.
  12. Fine-grained admin permissions V1 (fine-grain.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/admin-console-permissions/fine-grain.adoc, consulté le 07/10/2026.
  13. Admin CLI (admin-cli.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/admin-cli.adoc, consulté le 07/10/2026.
  14. Brute force detection (brute-force.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/threat/brute-force.adoc, consulté le 07/10/2026.
  15. RealmManager.java, valeurs par défaut d'un royaume, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/services/src/main/java/org/keycloak/services/managers/RealmManager.java, consulté le 07/10/2026.
  16. Configuring SSL for a realm (ssl.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/realms/ssl.adoc, consulté le 07/10/2026.
  17. Constants.java, durées par défaut, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/server-spi-private/src/main/java/org/keycloak/models/Constants.java, consulté le 07/10/2026.
  18. DefaultExportImportManager.java, valeurs par défaut des jetons de rafraîchissement, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java, consulté le 07/10/2026.
  19. Session and token timeouts (timeouts.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/sessions/timeouts.adoc, consulté le 07/10/2026.
  20. OIDC auth flows (con-oidc-auth-flows.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/sso-protocols/con-oidc-auth-flows.adoc, consulté le 07/10/2026.
  21. Auditing user events (login.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/events/login.adoc, consulté le 07/10/2026.
  22. Auditing admin events (admin.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/events/admin.adoc, consulté le 07/10/2026.
  23. JBossLoggingEventListenerProviderFactory.java, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/services/src/main/java/org/keycloak/events/log/JBossLoggingEventListenerProviderFactory.java, consulté le 07/10/2026.
  24. AdminEventBuilder.java, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/services/src/main/java/org/keycloak/services/resources/admin/AdminEventBuilder.java, consulté le 07/10/2026.
  25. OIDC client basic settings (con-basic-settings.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/clients/oidc/con-basic-settings.adoc, consulté le 07/10/2026.
  26. OIDC client advanced settings (con-advanced-settings.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/clients/oidc/con-advanced-settings.adoc, consulté le 07/10/2026.
  27. Unspecific redirect URIs (redirect.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/threat/redirect.adoc, consulté le 07/10/2026.
  28. Compromised access and refresh tokens (compromised-tokens.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/threat/compromised-tokens.adoc, consulté le 07/10/2026.
  29. Client policies (client-policies.adoc), dont l'exécuteur full-scope-disabled, tag 26.8.0, https://github.com/keycloak/keycloak/blob/26.8.0/docs/documentation/server_admin/topics/clients/client-policies.adoc, consulté le 07/10/2026.
  30. keycloak-default-client-profiles.json, profils de clients intégrés, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/services/src/main/resources/keycloak-default-client-profiles.json, consulté le 07/10/2026.
  31. Role scope mappings (con-role-scope-mappings.adoc), avertissement de dépréciation de Full Scope Allowed, tag 26.8.0, https://github.com/keycloak/keycloak/blob/26.8.0/docs/documentation/server_admin/topics/roles-groups/con-role-scope-mappings.adoc, consulté le 07/10/2026.
  32. RepresentationToModel.java, valeur par défaut de fullScopeAllowed, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/server-spi-private/src/main/java/org/keycloak/models/utils/RepresentationToModel.java, consulté le 07/10/2026.
  33. Managing the user profile (user-profile.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/users/user-profile.adoc, consulté le 07/10/2026.
  34. UsersResource.java, point d'API users/profile, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/services/src/main/java/org/keycloak/services/resources/admin/UsersResource.java, consulté le 07/10/2026.
  35. First login flow (first-login-flow.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/identity-broker/first-login-flow.adoc, consulté le 07/10/2026.
  36. General identity provider configuration, option Trust Email (configuration.adoc), tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/documentation/server_admin/topics/identity-broker/configuration.adoc, consulté le 07/10/2026.
  37. DefaultAuthenticationFlows.java, flux direct grant, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/server-spi-private/src/main/java/org/keycloak/models/utils/DefaultAuthenticationFlows.java, consulté le 07/10/2026.
  38. IdentityProvidersResource.java et RealmAdminResource.java, rôles requis en lecture, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/services/src/main/java/org/keycloak/services/resources/admin/IdentityProvidersResource.java, consulté le 07/10/2026.
  39. ServerInfoAdminResource.java, retour de la version, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java, consulté le 07/10/2026.
  40. OIDCConfigAttributes.java, attribut PKCE, tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/server-spi-private/src/main/java/org/keycloak/protocol/oidc/OIDCConfigAttributes.java, consulté le 07/10/2026.
  41. Configuring the Management Interface, source au tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/guides/server/management-interface.adoc, consulté le 07/10/2026.
  42. Tracking instance status with health checks, source au tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/guides/observability/health.adoc, consulté le 07/10/2026.
  43. Using a vault, source au tag 26.7.4, https://github.com/keycloak/keycloak/blob/26.7.4/docs/guides/server/vault.adoc, consulté le 07/10/2026.
  44. Secrets (env[].valueFrom.secretKeyRef), documentation Kubernetes, dépôt kubernetes/website, https://github.com/kubernetes/website/blob/main/content/en/docs/concepts/configuration/secret.md, consulté le 07/10/2026.
  45. Release 26.7.5 (correctifs de sécurité, dont CVE-2026-89298), dépôt keycloak/keycloak, https://github.com/keycloak/keycloak/releases/tag/26.7.5, consulté le 07/10/2026.
  46. Release 26.8.0 (correctifs de sécurité, dont CVE-2026-12388), dépôt keycloak/keycloak, https://github.com/keycloak/keycloak/releases/tag/26.8.0, consulté le 07/10/2026.
  47. Upgrading Guide, changements de la version 26.8.0 (secret masqué pour view-clients, CVE-2026-12388, dépréciation de Full Scope Allowed, échecs de connexion en base), tag 26.8.0, https://github.com/keycloak/keycloak/blob/26.8.0/docs/documentation/upgrading/topics/changes/changes-26_8_0.adoc, consulté le 07/10/2026.

Parlons de votre contexte.

Cet article expose une pratique générale ; votre situation a ses propres contraintes. Décrivez-la, nous répondons avec un périmètre.

Ouvrir le formulaire