Je développe une infrastructure de microservice basée sur Spring Cloud. Je veux sécuriser l'application avec Keycloak, qui fonctionne fondamentalement bien si l'utilisateur est authentifié.
Si l'utilisateur n'est pas authentifié, Keycloak génère l'erreur suivante:
Java.lang.ClassCastException: org.springframework.security.authentication.AnonymousAuthenticationToken cannot be cast to org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken
at org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade.getSecurityContext(SimpleHttpFacade.Java:63) ~[keycloak-spring-security-adapter-3.4.3.Final.jar:3.4.3.Final]
at org.keycloak.adapters.AuthenticatedActionsHandler.corsRequest(AuthenticatedActionsHandler.Java:102) ~[keycloak-adapter-core-3.4.3.Final.jar:3.4.3.Final]
at org.keycloak.adapters.AuthenticatedActionsHandler.handledRequest(AuthenticatedActionsHandler.Java:54) ~[keycloak-adapter-core-3.4.3.Final.jar:3.4.3.Final]
at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.Java:78) ~[keycloak-spring-security-adapter-3.4.3.Final.jar:3.4.3.Final]
at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:193) ~[Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:166) ~[Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.boot.actuate.trace.WebRequestTraceFilter.doFilterInternal(WebRequestTraceFilter.Java:110) ~[spring-boot-actuator-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:193) ~[Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:166) ~[Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:317) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.Java:127) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.Java:91) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.Java:114) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.Java:137) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.Java:111) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter.doFilter(KeycloakSecurityContextRequestFilter.Java:79) ~[keycloak-spring-security-adapter-3.4.3.Final.jar:3.4.3.Final]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.Java:170) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.Java:63) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter.doFilter(KeycloakAuthenticatedActionsFilter.Java:82) ~[keycloak-spring-security-adapter-3.4.3.Final.jar:3.4.3.Final]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.Java:200) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.Java:116) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter.doFilter(KeycloakPreAuthActionsFilter.Java:84) ~[keycloak-spring-security-adapter-3.4.3.Final.jar:3.4.3.Final]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.Java:100) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.Java:96) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.Java:64) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.Java:105) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.Java:56) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.Java:331) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.Java:214) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.Java:177) ~[spring-security-web-4.2.3.RELEASE.jar:4.2.3.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.Java:347) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.Java:263) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:193) ~[Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:166) ~[Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.Java:197) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:193) ~[Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:166) ~[Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.Java:106) ~[spring-boot-actuator-1.5.9.RELEASE.jar:1.5.9.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107) ~[spring-web-4.3.13.RELEASE.jar:4.3.13.RELEASE]
at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:193) ~[Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:166) ~[Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:199) ~[Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:96) [Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.keycloak.adapters.Tomcat.AbstractAuthenticatedActionsValve.invoke(AbstractAuthenticatedActionsValve.Java:67) [spring-boot-container-bundle-3.4.3.Final.jar:3.4.3.Final]
at org.Apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.Java:595) [Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.keycloak.adapters.Tomcat.AbstractKeycloakAuthenticatorValve.invoke(AbstractKeycloakAuthenticatorValve.Java:181) [spring-boot-container-bundle-3.4.3.Final.jar:3.4.3.Final]
at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:140) [Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:81) [Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:87) [Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:342) [Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.coyote.http11.Http11Processor.service(Http11Processor.Java:803) [Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.Java:66) [Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.Java:868) [Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.Tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.Java:1459) [Tomcat-embed-core-8.5.23.jar:8.5.23]
at org.Apache.Tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.Java:49) [Tomcat-embed-core-8.5.23.jar:8.5.23]
at Java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) [na:1.8.0_144]
at Java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [na:1.8.0_144]
at org.Apache.Tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.Java:61) [Tomcat-embed-core-8.5.23.jar:8.5.23]
at Java.lang.Thread.run(Unknown Source) [na:1.8.0_144]
La configuration de sécurité se présente comme suit:
@KeycloakConfiguration
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
{
private final KeycloakClientRequestFactory keycloakClientRequestFactory;
public SecurityConfig(KeycloakClientRequestFactory keycloakClientRequestFactory)
{
this.keycloakClientRequestFactory = keycloakClientRequestFactory;
}
/**
* define the actual constraints of the app.
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception
{
super.configure(http);
http
.cors()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.sessionAuthenticationStrategy(sessionAuthenticationStrategy())
.and()
.authorizeRequests()
.antMatchers("/*").hasRole("user")
.anyRequest().permitAll();
}
/**
* define the session auth strategy so that no session is created
*
* @return concrete implementation of session authentication strategy
*/
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy()
{
return new NullAuthenticatedSessionStrategy();
}
/**
* registers the Keycloakauthenticationprovider in spring context and sets its
* mapping strategy for roles/authorities (mapping to spring seccurities'
* default ROLE_... for authorities ).
*
* @param auth
* SecurityBuilder to build authentications and add details like
* authproviders etc.
* @throws Exception
*/
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception
{
KeycloakAuthenticationProvider keyCloakAuthProvider = keycloakAuthenticationProvider();
keyCloakAuthProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
auth.authenticationProvider(keyCloakAuthProvider);
}
/**
* Sets keycloaks config resolver to use springs application.properties
* instead of keycloak.json (which is standard)
*
* @return
*/
@Bean
public KeycloakConfigResolver KeyCloakConfigResolver()
{
return new KeycloakSpringBootConfigResolver();
}
/**
* Spring Boot attempts to eagerly register filter beans with the web
* application context. Therefore, when running the Keycloak Spring Security
* adapter in a Spring Boot environment, it may be necessary to add two
* FilterRegistrationBeans to your security configuration to prevent the
* Keycloak filters from being registered twice.
*
* @param filter
* @return
*/
@Bean
public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(
KeycloakAuthenticationProcessingFilter filter)
{
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
/**
* Spring Boot attempts to eagerly register filter beans with the web
* application context. Therefore, when running the Keycloak Spring Security
* adapter in a Spring Boot environment, it may be necessary to add two
* FilterRegistrationBeans to your security configuration to prevent the
* Keycloak filters from being registered twice.
*
* @param filter
* @return
*/
@Bean
public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(KeycloakPreAuthActionsFilter filter)
{
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
registrationBean.setEnabled(false);
return registrationBean;
}
}
Toute suggestion serait très appréciée.
Cordialement Blacky
J'ai le même problème.
Changer le client keycloak en support uniquement n'a pas résolu le problème.
Le problème réside dans les terminaux publics.
@Override
protected void configure( HttpSecurity http ) throws Exception {
super.configure( http );
http
.csrf().disable()
.sessionManagement()
.sessionCreationPolicy( SessionCreationPolicy.STATELESS )
.and()
.requestMatchers()
.and()
.authorizeRequests()
.antMatchers( "/tenants**" ).permitAll() // <- public endpoint
.anyRequest()
.authenticated();
}
Pour ces systèmes d'extrémité, Spring Security crée une authentification anonyme avec l'utilisateur fictif "anonymousUser". Cette authentification est une instance de AnonymousAuthenticationToken qui ne peut pas être convertie en KeycloakAuthenticationToken.
Si vous essayez de faire une demande à partir d'un client authentifié, comme une application angulaire, cela fonctionnera car il peut résoudre l'authentification via le jeton envoyé sur l'en-tête d'autorisation. C’est la raison pour laquelle l’approche réservée au porteur fonctionne dans les mêmes cas.
Je souhaite adresser une requête au serveur afin d’obtenir le domaine correct pour s’authentifier du côté angulaire. À ce moment-là, je n'ai pas de jeton d'authentification à envoyer, donc la sécurité de printemps créera l'authentification anonyme.
L'exception n'est levée que lorsque keycloak.cors = true.
Le problème se produit lorsque la méthode getSecurityContext () de SimpleHttpFacade.class est appelée sur la classe AuthenticatedActionsHandler.class par la méthode corsRequest ().
Quelqu'un at-il une solution de travail?
Meilleures salutations
Utilisez la dépendance Spring Boot 2
de Keycloak comme dans:
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-2-starter</artifactId>
</dependency>
! Notez le -2-
dans l'identifiant d'artefact.
Le parent Spring Boot étant:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/>
</parent>
La dépendance de Keycloak étant:
<properties>
<keycloak.version>4.0.0.Final</keycloak.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>${keycloak.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Dans votre http HttpSecurity, ajoutez .anonymous().disable()
pour que vous ayez Votre HttpSecurity comme http.anonymous().disable()
.
Couru dans cette même erreur aujourd'hui. Résolu en échangeant simplement keycloak http.AuthorizeRequest de permitAll () à authentifié () pour anyRequest ().
pom.xml (non édité)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
...
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.keycloak.bom</groupId>
<artifactId>keycloak-adapter-bom</artifactId>
<version>4.1.0.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
KeycloakSecurityConfig.Java (OLD)
/**
* We require the user to be logged in for every single request
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/entry/sub/*").hasRole("roleA")
.anyRequest().permitAll();
}
KeycloakSecurityConfig.Java (NEW)
/**
* We require the user to be logged in for every single request
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests()
.antMatchers("/entry/sub/*").hasRole("roleA")
.anyRequest().authenticated();
}
L'utilisation de la version 3.3.0.Final
pour le démarreur et l'adaptateur fonctionne pour moi. Lorsque je modifie la version en 3.4.3.Final
, je reçois la même exception.
J'utilise le serveur Keycloak 3.4.3 (autonome) ...
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-security-adapter</artifactId>
<version>3.3.0.Final</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
<version>3.3.0.Final</version>
</dependency>
Tout le monde connaît une solution pour utiliser la version actuelle des dépendances?
J'ai eu le même problème dans mon architecture de microservice. Selon ce ceci réponse de Stian Thorgersen, tous les services ReST devraient être réservés au support. Ils doivent donc accepter un jeton, mais ne jamais effectuer de redirection vers la page de connexion.
Par conséquent, j'ai extrait le composant d'interface utilisateur du service et le sers sur une instance distincte de NGINX. L'interface utilisateur effectue la redirection vers ma page de connexion Keycloak et ajoute le jeton à chaque requête GET/POST/quelconque supplémentaire aux services sécurisés. J'ai changé tous les services ReST en keycloak.bearer-only=true
, à la fois dans le service et dans la configuration Keycloak. Cela fonctionne maintenant comme un charme.
J'espère que cela vous aide.
Freddy
Nous voulons que les développeurs se connectent à la passerelle API et appellent directement le service. J'ai finalement atteint cet objectif en ajoutant un filtre qui étend la ZuulFilter
de base:
public class KeycloakAuthorizationFilter extends ZuulFilter
{
private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String BEARER_TOKEN_TYPE = "Bearer";
private static Logger log = LoggerFactory.getLogger(KeycloakAuthorizationFilter.class);
@Override
public Object run()
{
log.info("Adding authenticaton header...");
RequestContext ctx = RequestContext.getCurrentContext();
if (ctx.getZuulRequestHeaders().containsKey(AUTHORIZATION_HEADER)) return null;
KeycloakAuthenticationToken authentication = (KeycloakAuthenticationToken) SecurityContextHolder.getContext()
.getAuthentication();
if(authentication == null)
{
log.error("Could not load authenticaton from security context!");
}
else if(authentication.isAuthenticated() == false)
{
log.error("Not authenticated!");
}
else
{
Object principal = authentication.getPrincipal();
if(principal != null && principal instanceof KeycloakPrincipal)
{
@SuppressWarnings("unchecked")
KeycloakPrincipal<KeycloakSecurityContext> keycloakPrincipal = (KeycloakPrincipal<KeycloakSecurityContext>) authentication
.getPrincipal();
log.info(String.format("Constructing Header %s for Token %s", AUTHORIZATION_HEADER, BEARER_TOKEN_TYPE));
ctx.addZuulRequestHeader(AUTHORIZATION_HEADER, String.format("%s %s", BEARER_TOKEN_TYPE, keycloakPrincipal.getKeycloakSecurityContext().getTokenString()));
}
}
return null;
}
@Override
public boolean shouldFilter()
{
return true;
}
@Override
public int filterOrder()
{
return 0;
}
@Override
public String filterType()
{
return "pre";
}
}
Ceci fonctionne simplement génial et vous donne beaucoup plus de flexibilité.