spring-securityopenidspring-cloud-gatewayspring-cloud-security

Spring Cloud Security with Token Relay: Response has empty set cookie header


I try building a minimal openid secured cloud environment. Following more or less https://developer.okta.com/blog/2019/08/28/reactive-microservices-spring-cloud-gateway .

I have a spring cloud gateway, a consul registry, an application registered on okta and a simple test app with just one controller returning a string. Both the gateway and the test application depend on 'com.okta.spring', name: 'okta-spring-boot-starter', version: '1.4.0'.

The gateway is configured like so (skipping ssl here for brevity):

spring:
  cloud:
    loadbalancer:
      ribbon:
        enabled: false
    gateway:
      default-filters: 
        - TokenRelay
      discovery:
        locator:
          enabled: true
okta:
  oauth2:
    issuer: ${OKTA_OAUTH2_ISSUER}
    client-id: ${OKTA_OAUTH2_CLIENT_ID}
    client-secret: ${OKTA_OAUTH2_CLIENT_SECRET}

and i added a minimal security configuration:

private final ReactiveClientRegistrationRepository clientRegistrationRepository;

@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
    http
            .redirectToHttps()
            .and()
            .authorizeExchange()
            .pathMatchers("/login").permitAll()
            .pathMatchers("/actuator/**").permitAll()
            .anyExchange().authenticated()
            .and()
            .oauth2Login()
            .and()
            .logout(logout -> logout.logoutSuccessHandler(oidcLogoutSuccessHandler()))
            .oauth2ResourceServer()
            .jwt();
    return http.build();
}

private ServerLogoutSuccessHandler oidcLogoutSuccessHandler() {
    OidcClientInitiatedServerLogoutSuccessHandler oidcLogoutSuccessHandler =
            new OidcClientInitiatedServerLogoutSuccessHandler(clientRegistrationRepository);

    oidcLogoutSuccessHandler.setPostLogoutRedirectUri(URI.create("https://<my-uri>"));

    return oidcLogoutSuccessHandler;
}

The test application also has okta openid configured in the application.yml as in the gateway plus:

@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
    http
            .authorizeExchange()
            .pathMatchers("/actuator/**").permitAll()
            .anyExchange().authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt();

    Okta.configureResourceServer401ResponseBody(http);

    return http.build();
}

My problem is:

When I remove the token relay and keep the test application un-secure the gateway will successfully do the authorization and the response contains a set-cookie header that can be used in subsequent requests to provide from running through all the authorization flow again.

However, adding token relay by means of 'org.springframework.cloud:spring-cloud-starter-security' (and configured as a default-filter as shown above), returns an empty set-cookie header and thus each and every request as to run throw the whole authorization flow.

I tried different solution approaches, like manually configuring ReactiveOAuth2AuthorizedClientService. My approaches all felt more like guessing.


Solution

  • It turned out, the solution is to remove the cookie header from the downstream request. This can be achieved by adding another default filter to the gateway:

    spring:
      cloud:
        gateway:
          default-filters: 
            - TokenRelay=
            - RemoveRequestHeader=Cookie