I am using the following dependencies in one application: Spring-Cloud-Gateway, Spring Boot OAuth2 Client, Spring Boot OAuth2 Resource Server.
I use the following security config:
@Bean
public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http, ReactiveClientRegistrationRepository clientRegistrationRepository) {
http.oauth2Login();
http.logout(logout -> logout.logoutSuccessHandler(
new OidcClientInitiatedServerLogoutSuccessHandler(clientRegistrationRepository)));
http.authorizeExchange()
.pathMatchers("/actuator/health").permitAll()
.pathMatchers("/auth/realms/ahearo/protocol/openid-connect/token").permitAll()
.pathMatchers("/v3/api-docs").permitAll()
.anyExchange().authenticated()
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(userJwtAuthenticationConverter());
http.csrf().disable().formLogin().disable().httpBasic().disable();
return http.build();
}
@Bean
public UserJwtAuthenticationConverter userJwtAuthenticationConverter() {
return new UserJwtAuthenticationConverter();
}
When I execute calls I am correctly advised to login which works fine. But it's just the Authentication that works, not the Authorization. When I use the debugger I can see that the userJwtAuthenticationConverter()
method is never called to use roles out of the JWT.
When I use the same method in another application/microservice which is just a OAuth2 Resource Server, but not a OAuth2 Client the method is correctly called and executed.
The security config in the application.yaml looks like the following in the Spring Cloud Gateway application:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: http://localhost/auth/realms/example-realm
jwk-set-uri: http://localhost/auth/realms/example-realm/protocol/openid-connect/certs
client:
registration:
keycloak:
client-id: 'example-proxy-client'
client-secret: 'xxx'
authorizationGrantType: authorization_code
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
scope: openid,profile,email
provider:
keycloak:
issuer-uri: http://localhost/auth/realms/example-realm
user-name-attribute: preferred_username
Isn't it possible for the Spring Cloud Gateway application to perform as a OAuth2 Client and Resource Server at the same time or am I doing a mistake regarding the configuring of the application?
Turns out that I misunderstood some basic OAuth2 concepts. The Authorization itself is working correctly when I send a JWT in the Authorization header (Implicit Flow). What did not work is the case when I tried to access a resource via the browser. I got redirected to the login page of Keycloak (Authorization Code Flow). After you sign in through the login page of Keycloak you do not receive the JWT but a Keycloak Session ID. Spring Cloud Gateway cannot perform Authorization on the basis of a Keycloak Session ID (do not know how that would work if I wanted to use Authorization Code Flow but I am using Implicit flow, so I am fine for now).