Search code examples
springspring-bootspring-securityoauth-2.0spring-cloud

Authorization not working in Gateway with OAuth2 Client + Resource Server


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?


Solution

  • 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).