4

I'm configuring spring cloud api gateway to support several security chains. To do that I'm using several security filter chains which triggered on specific security header presence:

  1. The legacy one which already use Authorization header
  2. And new implementation, that integrated with external idp. This solution utilize resource service capabilities. And for this chain I'd like to use, lets say "New-Auth" header.

In case I tune my current setup to trigger second (idp) chain on Authorization header presence (and make call with IDP token), then everything works fine. This way security chain validates token that it expect in Authorization header against idp jwk. But this header is already reserved for legacy auth.

I guess I need a way to point spring resource server chain a new header name to look for.

My security dependencies:

implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-oauth2-resource-server'

My configuration

@EnableWebFluxSecurity
public class WebSecurityConfiguration {

  // ...

  @Bean
  @Order(1)
  public SecurityWebFilterChain iamAuthFilterChain(ServerHttpSecurity http) {
    ServerWebExchangeMatcher matcher = exchange -> {
      HttpHeaders headers = exchange.getRequest().getHeaders();
      List<String> strings = headers.get(SurpriseHeaders.IDP_AUTH_TOKEN_HEADER_NAME);
      return strings != null && strings.size() > 0
          ? MatchResult.match() : MatchResult.notMatch();
    };

    http
        .securityMatcher(matcher)
        .csrf().disable()
        .authorizeExchange()
          .pathMatchers(navigationService.getAuthFreeEndpoints()).permitAll()
          .anyExchange().authenticated()
        .and()
          .oauth2ResourceServer(OAuth2ResourceServerSpec::jwt)
          .oauth2ResourceServer().jwt().jwkSetUri(getJwkUri())
          .and()
        .and()
          .addFilterAt(new LoggingFilter("idpAuthFilterChain"), SecurityWebFiltersOrder.FIRST)
          .addFilterAfter(new IdpTokenExchangeFilter(authClientService), SecurityWebFiltersOrder.AUTHENTICATION)
    ;    
    return http.build();
  }

}

Dirty solution:

We can add some filter to edit request and duplicate incoming "New-Auth" header as an "Authorization" header at a beginning of security filter chain.

Looks like it works, but I believe it should be a better way.

Silk0vsky
  • 941
  • 1
  • 18
  • 34

2 Answers2

7

You can specify a ServerAuthenticationConverter to your oauth2ResourceServer configuration, like so:

http
    .oauth2ResourceServer((resourceServer) -> resourceServer
        .bearerTokenConverter(customBearerTokenAuthenticationConverter())
        .jwt()
    );

ServerAuthenticationConverter customBearerTokenAuthenticationConverter() {
    ServerBearerTokenAuthenticationConverter tokenAuthenticationConverter = new ServerBearerTokenAuthenticationConverter();
    tokenAuthenticationConverter.setBearerTokenHeaderName("New-Auth");
    return tokenAuthenticationConverter;
}
  • Hi, @Marcus. http.oauth2ResourceServer allows me to configure OAuth2ResourceServerSpec which doesn't have methods for BearerTokenResolver configuration. Probably we are talking about different security realizations. The `http.oauth2ResourceServer` implementation I'm using lies in `org.springframework.security:spring-security-config5.5.0` – Silk0vsky Nov 04 '21 at 16:41
  • I've updated my answer to reactive applications – Marcus Hert da Coregio Nov 04 '21 at 16:51
  • It works, thanks! – Silk0vsky Nov 04 '21 at 17:08
2

thats for the servlet stack, the other reply you can see is for the reactive stack

@Bean
BearerTokenResolver bearerTokenResolver() {
    DefaultBearerTokenResolver bearerTokenResolver = new DefaultBearerTokenResolver();
    bearerTokenResolver.setBearerTokenHeaderName(HttpHeaders.PROXY_AUTHORIZATION);
    return bearerTokenResolver;
}

see reference here : https://docs.spring.io/spring-security/reference/servlet/oauth2/resource-server/bearer-tokens.html

sahi4j
  • 21
  • 1