How to Fix Keycloak Logout Issue With Spring Cloud Gateways

  1. Spring Cloud Gateway Keycloak OAuth2 OIDC Integration
  2. Spring Cloud Gateway — Resource Server with Keycloak RBAC

What is the exact problem?

Fixing the Logout Issue with Keycloak

@Bean
public ServerLogoutSuccessHandler keycloakLogoutSuccessHandler(ReactiveClientRegistrationRepository repository) {

OidcClientInitiatedServerLogoutSuccessHandler oidcLogoutSuccessHandler =
new OidcClientInitiatedServerLogoutSuccessHandler(repository);

oidcLogoutSuccessHandler.setPostLogoutRedirectUri("{baseUrl}/logout.html");

return oidcLogoutSuccessHandler;
}
security:
oauth2:
client:
provider:
my-keycloak-provider:
issuer-uri: http://localhost:8080/realms/My-Realm
registration:
keycloak-spring-gateway-client:
provider: my-keycloak-provider
scope: openid
client-id: spring-gateway-client
client-secret: 3RhEF8pqKTANrQ6BhfxaYVmcjTXsDK0u
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/keycloak"
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http, ServerLogoutSuccessHandler handler) {

http
.authorizeExchange()
.pathMatchers("/actuator/**", "/","/logout.html")
.permitAll()
.and()
.authorizeExchange()
.anyExchange()
.authenticated()
.and()
.oauth2Login() // to redirect to oauth2 login page.
.and()
.logout()
.logoutSuccessHandler(handler);


return http.build();
}

Understanding this a little deeper

@Override
public Mono<Void> onLogoutSuccess(WebFilterExchange exchange, Authentication authentication) {

return Mono.just(authentication)
.filter(OAuth2AuthenticationToken.class::isInstance)
.filter((token) -> authentication.getPrincipal() instanceof OidcUser)
.map(OAuth2AuthenticationToken.class::cast)
.map(OAuth2AuthenticationToken::getAuthorizedClientRegistrationId)
.flatMap(this.clientRegistrationRepository::findByRegistrationId)
.flatMap((clientRegistration) -> {
URI endSessionEndpoint = endSessionEndpoint(clientRegistration);
if (endSessionEndpoint == null) {
return Mono.empty();
}
String idToken = idToken(authentication);
String postLogoutRedirectUri = postLogoutRedirectUri(exchange.getExchange().getRequest());
return Mono.just(endpointUri(endSessionEndpoint, idToken, postLogoutRedirectUri));
})
....

Conclusion

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Amrut Prabhu

Amrut Prabhu

Software Craftsman, Tech Enthusiast. I run https://refactorfirst.com to post all my articles