I migrate from Zuul Gateway to Spring Gateway. This forced me to abandon Servlets for Webflux. I use KeyCloak and KeyCloak roles for authentication and authorization.
There is no official reactive KeyCloak implementation, so I use Spring OAuth2 instead. It works fine apart from retrieving the roles.
I cannot use servlet interceptors, because servlets are not allowed by WebFlux. Also, it seems Spring Gateway in general does not allow intercepting response bodies.
Thus my problem remains: How do I retrieve KeyCloak roles in Spring Gateway, so that they can be used by its security?
Here is some sample code I use: In class SecurityConfig.java:
@Bean public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) { http.csrf().disable().authorizeExchange(exchanges -> exchanges.pathMatchers("/**").hasAnyRole("DIRECTOR")); }
application.yml:
spring.security.oauth2.client.provider.keycloak.issuer-uri: ..../realms/default
I am having the same problem myself. One of the problems I am getting its getting copies of things like the
JWTtag i.e. the text thatKeycloakhas encode you settingsThis code will get you some of the values that are part of the conversation, the Token part is the
JWTtoken, you can copy and paste that intojwt.ioand find out what whatKeycloakhas actually sent.This normally looks like
}
As you can see
Keycloaksupports two different types of ROLE tokens, but they are not defined in top level, but underrealm_accessandresource_access, the difference being resource access defines ROLE that are part of a resource and real_access defines roles that are defined across all realms.To get these values defined, its necessary to define a Mapper, as follows
To load these values in to Spring security you need to define a
userAuthoritiesMapperBean and export the settings found in the attributes asSimpleGrantedAuthority, as follows.Please note this code is based on a sample found at OAuth2 Login with custom granted authorities from UserInfo The access to Attributes is my own work.
Note an error message will be generated at the highest level if no
realm_accessorresource_accessis found, as I assume that wanting to decode aKeycloakreference is the reason for using this code.When working correctly, it generates the following output