Le cheminement est un peu différent d’un JWT fait maison. Dans un schéma classique JWT, c’est votre application Spring Boot qui reçoit le login/mot de passe, vérifie l’utilisateur, puis génère le JWT. Avec Keycloak, ce n’est plus votre application qui gère directement le login/mot de passe. C’est Keycloak qui devient le serveur d’authentification.
Votre schéma :
1. L’utilisateur envoie son login et mot de passe 2. Le serveur vérifie que les 2 sont ok 3. Le serveur génère un JWT 4. Le client envoie le JWT dans les requêtes suivantes 5. Le serveur valide le token
Dans ce cas :
Navigateur → Application Spring Boot
L’application Spring Boot fait tout :
authentification vérification du mot de passe génération du token validation du token gestion des rôles
Avec Keycloak, le cheminement devient :
1. L’utilisateur demande une page protégée dans Spring Boot 2. Spring Boot redirige l’utilisateur vers Keycloak 3. L’utilisateur saisit son login et mot de passe dans Keycloak 4. Keycloak vérifie le login et le mot de passe 5. Keycloak renvoie l’utilisateur vers Spring Boot avec un code d’autorisation 6. Spring Boot échange ce code contre des tokens auprès de Keycloak 7. Spring Boot crée une session web pour l’utilisateur 8. L’utilisateur navigue dans l’application Thymeleaf avec un cookie de session 9. Spring Security utilise les informations Keycloak pour connaître l’utilisateur et ses rôles
Supposons une application Spring Boot avec ces pages :
/ page publique /chiens page protégée /admin page réservée aux administrateurs
L’utilisateur va sur :
GET http://localhost:8080/chiens
Spring Security voit que la page est protégée, il redirige vers Keycloak :
http://localhost:8081/realms/wouafwouaf/protocol/openid-connect/auth...
L’utilisateur ne saisit pas son mot de passe dans votre application Thymeleaf. Il le saisit dans Keycloak :
Login : philippe Mot de passe : ****
Keycloak vérifie :
utilisateur existe-t-il ? mot de passe est-il correct ? compte est-il actif ? rôle est-il attribué ?
Si tout est correct, Keycloak ne donne pas directement la page /chiens.
/chiens
Il redirige vers Spring Boot avec un code d’autorisation.
Spring Boot reçoit un code, puis contacte Keycloak en arrière-plan. Keycloak renvoie notamment :
access_token id_token refresh_token
L’access_token est souvent un JWT. Mais dans une application Thymeleaf, ce token n’est généralement pas manipulé directement par vos templates.
access_token
Spring Security l’utilise pour établir l’authentification.
Pour une application web classique Thymeleaf, Spring Boot fonctionne souvent avec une session HTTP. Le navigateur reçoit un cookie :
JSESSIONID=...
Ensuite, à chaque page demandée :
GET /chiens Cookie: JSESSIONID=...
Le navigateur n’a pas besoin d’envoyer manuellement :
Authorization: Bearer eyJhbGciOi...
C’est une différence importante avec une API REST pure.
Navigateur | | 1. Demande /chiens v Spring Boot + Thymeleaf | | 2. Redirection login v Keycloak | | 3. Login / mot de passe | 4. Authentification OK v Spring Boot | | 5. Récupère les tokens | 6. Crée une session v Navigateur | | 7. Navigue avec JSESSIONID v Pages Thymeleaf protégées
Oui, mais pas de la même manière.
Avec Thymeleaf :
Keycloak génère bien des tokens, dont souvent un JWT. Spring Boot les reçoit et les utilise. Mais le navigateur navigue ensuite surtout avec un cookie de session.
Avec une API REST pure :
Le front-end envoie souvent directement le JWT dans l’en-tête Authorization vers le back-end
Donc :
Application Thymeleaf = logique session web Application API REST = logique Bearer Token
Dans une application Thymeleaf, on configure plutôt Spring Boot comme OAuth2 Client.
Exemple simplifié :
spring: security: oauth2: client: registration: keycloak: client-id: wouafwouaf-thymeleaf client-secret: secret scope: openid, profile, email authorization-grant-type: authorization_code redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}" provider: keycloak: issuer-uri: http://localhost:8081/realms/wouafwouaf
Ici, Spring Boot dit :
Je délègue la connexion à Keycloak.
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { return http .authorizeHttpRequests(auth -> auth .requestMatchers("/", "/css/**", "/js/**").permitAll() .requestMatchers("/admin/**").hasRole("ADMIN") .anyRequest().authenticated() ) .oauth2Login(oauth2 -> oauth2 .defaultSuccessUrl("/chiens", true) ) .logout(logout -> logout .logoutSuccessUrl("/") ) .build(); } }
Avec cette configuration :
/ accessible sans connexion /css/** accessible sans connexion /admin/** réservé au rôle ADMIN autres pages utilisateur connecté obligatoire
Pour Thymeleaf, on utilise généralement :
spring-boot-starter-oauth2-client
Pourquoi ?
Parce que l’application web redirige l’utilisateur vers Keycloak, récupère les tokens, puis gère une session.
Spring Boot = OAuth2 Client
Pour une API REST, on utilise généralement :
spring-boot-starter-oauth2-resource-server
Parce que l’API reçoit des requêtes avec :
Et elle doit vérifier le JWT.
Spring Boot = Resource Server
Navigateur → Spring Boot login/mot de passe → Spring Boot Spring Boot génère le JWT Navigateur renvoie le JWT Spring Boot valide le JWT
Navigateur → Spring Boot Spring Boot redirige vers Keycloak Keycloak vérifie login/mot de passe Keycloak renvoie vers Spring Boot Spring Boot récupère les tokens Spring Boot crée une session Navigateur navigue avec JSESSIONID
Avec Keycloak :
Votre application ne vérifie plus le mot de passe. Votre application fait confiance à Keycloak.
Le JWT existe côté sécurité, mais l’utilisateur navigue surtout avec une session web.
Avec une API REST :
Le JWT est envoyé explicitement dans chaque requête HTTP.
Donc, avec Spring Boot + Thymeleaf, le cheminement équivalent est :
1. L’utilisateur demande une page protégée 2. Spring Boot redirige vers Keycloak 3. Keycloak récupère login/mot de passe 4. Keycloak authentifie l’utilisateur 5. Keycloak renvoie vers Spring Boot 6. Spring Boot récupère et valide les tokens 7. Spring Boot crée une session utilisateur 8. Thymeleaf affiche les pages selon les rôles