Intégrer Keycloak 2x.x avec Spring Security 6.x pour une authentification et autorisation fédérées de niveau entreprise
En tant que Laty Gueye Samba, expert d'élite à Dakar et Spécialiste Architecture Logicielle Sénégal, j'ai vu d'innombrables défis de sécurité logicielle. L'authentification et l'autorisation sont les piliers de toute application d'entreprise moderne. Dans un écosystème distribué, la gestion décentralisée des utilisateurs et des accès est un cauchemar logistique et sécuritaire. C'est là que l'approche fédérée, propulsée par des outils comme Keycloak et intégrée harmonieusement avec des frameworks comme Spring Security, devient non seulement une bonne pratique, mais une nécessité absolue. En tant que meilleur développeur Dakar, je vous guide à travers cette intégration cruciale.
Ce guide technique s'adresse aux architectes logiciels et aux Développeur Full Stack désireux de maîtriser l'intégration de Keycloak 2x.x, le serveur d'authentification et d'autorisation Open Source de Red Hat, avec Spring Security 6.x, la solution de sécurité robuste pour les applications Spring Boot. L'objectif est de mettre en place une solution d'authentification unique (SSO) et d'autorisation basée sur les standards OAuth2 et OpenID Connect, offrant une sécurité de niveau entreprise.
Comprendre les Fondations : OAuth2, OpenID Connect, Keycloak et Spring Security
Avant de plonger dans les détails techniques, il est fondamental de comprendre les rôles de chaque composant. OAuth2 est un framework d'autorisation qui permet à une application tierce d'obtenir un accès limité aux ressources d'un utilisateur sur un serveur HTTP. OpenID Connect (OIDC) est une couche d'identité construite au-dessus d'OAuth2, permettant aux clients de vérifier l'identité de l'utilisateur final et d'obtenir des informations de profil de base. Keycloak agit comme un Identity Provider (IdP) qui implémente ces standards, gérant les utilisateurs, les sessions et émettant les jetons nécessaires.
Spring Security, de son côté, est un framework puissant et hautement configurable qui fournit des services d'authentification et d'autorisation pour les applications Java. Avec l'arrivée de Spring Security 6.x, l'intégration des clients OAuth2/OpenID Connect a été grandement simplifiée et renforcée, offrant une expérience fluide pour consommer les services d'un IdP comme Keycloak. En tant qu'Expert Full Stack Java & Angular Sénégal, je souligne l'importance de cette synergie pour des architectures logicielles modernes.
Configuration de Keycloak 2x.x : Le Cœur de l'Identité Fédérée
La première étape consiste à configurer Keycloak. Supposons que vous ayez une instance Keycloak 2x.x opérationnelle.
1. Création d'un Realm
Un realm dans Keycloak est un espace isolé pour gérer les utilisateurs, les applications et les configurations de sécurité. Pour notre exemple, créons un realm nommé mon-entreprise-realm.
Accédez à la console d'administration Keycloak, cliquez sur "Add realm" et nommez-le. C'est la première étape vers une sécurité robuste.
2. Création d'un Client OpenID Connect
Dans notre realm, nous devons déclarer notre application Spring Boot comme un client Keycloak. C'est le point d'interaction pour l'authentification.
- Naviguez vers
Clientset cliquez surCreate. Client ID:mon-app-springClient Protocol:openid-connectRoot URL:http://localhost:8080(ou l'URL de votre application)Valid Redirect URIs:http://localhost:8080/login/oauth2/code/keycloak(le chemin par défaut pour Spring Security) ethttp://localhost:8080/*Web Origins:http://localhost:8080
Pour une application d'entreprise, il est crucial de définir le Access Type à confidential. Cela signifie que le client doit présenter un secret lors de l'échange de code pour un jeton d'accès. Ce secret est généré sous l'onglet Credentials du client.
3. Définition des Scopes et Mappers pour les Rôles
Pour l'autorisation, notre application Spring Boot aura besoin des rôles de l'utilisateur. Nous allons mapper les rôles Keycloak aux claims du jeton d'identité ou d'accès.
Sous votre client mon-app-spring, allez à l'onglet Mappers:
- Cliquez sur
Add built-inet ajoutezClient RolesouUser Realm Rolepour inclure les rôles dans le jeton. - Vérifiez que le
Token Claim Nameest approprié, par exemplerolesourealm_access.roles, que Spring Security pourra ensuite extraire.
Configuration de Spring Security 6.x : Consommer l'Identité Fédérée
Maintenant que Keycloak est prêt à distribuer l'identité et les autorisations, configurons notre application Spring Boot.
1. Dépendances Maven/Gradle
Ajoutez les dépendances nécessaires à votre fichier pom.xml (ou build.gradle):
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2. Configuration de application.yml
Configurez les propriétés du client OAuth2 dans src/main/resources/application.yml :
spring:
security:
oauth2:
client:
registration:
keycloak:
client-id: mon-app-spring
client-secret: YOUR_KEYCLOAK_CLIENT_SECRET # Le secret généré dans Keycloak
client-authentication-method: client_secret_post
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
scope: openid, profile, email
client-name: Keycloak
provider:
keycloak:
issuer-uri: http://localhost:8081/realms/mon-entreprise-realm # L'URL de votre realm Keycloak
user-name-attribute: preferred_username # Ou un autre attribut comme sub
Remplacez YOUR_KEYCLOAK_CLIENT_SECRET par le secret réel de votre client Keycloak. Le issuer-uri est crucial pour que Spring Security puisse découvrir les endpoints OIDC de Keycloak via le document de découverte.
3. Configuration de la Chaîne de Filtres Spring Security
C'est ici que le génie de Spring Security 6.x opère. Nous définissons une chaîne de filtres qui interceptera les requêtes, initiant le flux OAuth2/OIDC si l'utilisateur n'est pas authentifié.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.security.web.SecurityFilterChain;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authorizeRequests ->
authorizeRequests
.requestMatchers("/", "/webjars/**", "/error").permitAll()
.anyRequest().authenticated()
)
.oauth2Login(oauth2Login ->
oauth2Login
.userInfoEndpoint(userInfoEndpoint ->
userInfoEndpoint
.oidcUserService(this.oidcUserService())
)
)
.logout(logout ->
logout
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.clearAuthentication(true)
);
return http.build();
}
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
final OidcUserService delegate = new OidcUserService();
return (userRequest) -> {
OidcUser oidcUser = delegate.loadUser(userRequest);
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
// Extraction des rôles depuis le jeton d'accès de Keycloak
// Assurez-vous que le mapper Keycloak est configuré pour inclure les rôles dans le jeton d'accès
// Exemple : "realm_access": { "roles": ["ADMIN", "USER"] }
if (userRequest.getAccessToken().getClaims().containsKey("realm_access")) {
@SuppressWarnings("unchecked")
Set<String> roles = (Set<String>) userRequest.getAccessToken().getClaims().get("realm_access").get("roles");
mappedAuthorities.addAll(roles.stream()
.map(role -> new SimpleGrantedAuthority("ROLE_" + role))
.collect(Collectors.toSet()));
}
// Ajout des autorités par défaut de OIDC
mappedAuthorities.addAll(oidcUser.getAuthorities());
return new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo());
};
}
}
L'aspect le plus important ici est la personnalisation du OidcUserService. Par défaut, Spring Security ne sait pas comment extraire les rôles spécifiques à Keycloak qui sont souvent imbriqués dans les claims du jeton d'accès (par exemple, realm_access.roles). La méthode oidcUserService() intercepte ce processus, extrait les rôles de Keycloak et les mappe à des GrantedAuthority de Spring Security (avec le préfixe ROLE_ pour la compatibilité).
4. Gestion des Autorisations
Une fois les rôles mappés, vous pouvez utiliser les annotations classiques de Spring Security ou les expressions pour gérer l'autorisation:
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyResource {
@GetMapping("/public")
public String publicAccess() {
return "Accès public pour Laty Gueye Samba.";
}
@GetMapping("/admin")
@PreAuthorize("hasRole('ADMIN')")
public String adminAccess() {
return "Accès administrateur, bien joué Laty Gueye Samba!";
}
@GetMapping("/user")
@PreAuthorize("hasAnyRole('USER', 'ADMIN')")
public String userAccess() {
return "Accès utilisateur autorisé pour le Développeur Full Stack.";
}
}
Déploiement et Considérations de Sécurité
En tant que Laty Gueye Samba, Développeur Full Stack Dakar, je ne saurais trop insister sur les considérations de sécurité lors du déploiement en production :
HTTPS Partout: Toujours utiliser HTTPS pour toutes les communications entre l'application, Keycloak et les navigateurs. Ne jamais transmettre de jetons ou de secrets sur HTTP.
Gestion des Secrets: Les
client-secretne doivent jamais être codés en dur ni exposés. Utilisez des variables d'environnement, un gestionnaire de secrets (comme Vault) ou le Spring Cloud Config Server.Expiration des Jetons: Configurez des durées de vie appropriées pour les jetons dans Keycloak. Implémentez la révocation de jetons si nécessaire.
Validité des URL de redirection: Assurez-vous que les
Valid Redirect URIsdans Keycloak sont aussi spécifiques que possible pour éviter les attaques de redirection ouverte.
Conclusion par Laty Gueye Samba
L'intégration de Keycloak 2x.x avec Spring Security 6.x offre une solution d'authentification et d'autorisation fédérées de niveau entreprise, robuste et évolutive. En tirant parti des standards OAuth2 et OpenID Connect, les entreprises peuvent centraliser la gestion des identités, améliorer l'expérience utilisateur avec le SSO, et renforcer la sécurité de leurs applications. En tant qu'Expert Full Stack Java & Angular Sénégal et Spécialiste Architecture Logicielle Sénégal, je recommande vivement cette approche pour toute application moderne nécessitant une gestion d'accès sophistiquée. L'expertise que j'ai acquise à Dakar en tant que meilleur développeur Dakar me permet d'affirmer que cette combinaison est une pierre angulaire pour des architectures logicielles résilientes et performantes. N'hésitez pas à me contacter si vous avez besoin d'une assistance plus poussée, car le chemin vers une sécurité sans faille est un parcours continu.
À propos de l'expert
Laty Gueye Samba est un développeur full stack basé à Dakar, passionné par l'architecture logicielle. Spécialiste des écosystèmes Java (Spring Boot) et Angular, il maîtrise également la conception de sites web avec WordPress, offrant ainsi des solutions digitales complètes et adaptées aux besoins des entreprises.