1

I used to use a Zuul gateway for my microservice environment. I have set up my own OAUTH2 service, which is using the Spring Security OAUTH2 library for it's configuration. In Zuul I had found a 'trick' to use a remote token service, which pointed to my internal OAUTH2 service. (configuration class below) This worked like a charm.

Now I also have to use Websockets for another piece of the (web) application. I've found that zuul doesn't support websockets, and I couldn't figure out how I should go about to upgrading to zuul 2 (I couldn't get the example OAUTH2 project to run).

So I turned to the new Spring Cloud Gateway, which is supposed to support websockets. But, now I'm working on re-configuring the gateway, and I can't seem to be able to figure out how I should configure it to use my own resourceserver.

The code I used / tried:

My original RemoteTokenService config. The values are stored in an .env file, and the uri pointed to zuul + /api/oauth/token.

@Configuration
public class OAuth2ResourceServerConfigRemoteTokenService extends ResourceServerConfigurerAdapter {
    @Value("${security.oauth2.client.client-id}")
    private String clientId;
    @Value("${security.oauth2.client.client-secret}")
    private String clientSecret;
    @Value("${security.oauth2.token.uri}")
    private String tokenUrl;

    @Override
    public void configure(final HttpSecurity http) throws Exception {
        // @formatter:off
        //TODO: Check what this exactly does (forces the need of a session?)
        http.cors().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                .and()
                .authorizeRequests().anyRequest().permitAll();
        // @formatter:on                
    }

    /**
     * Tells OAuth where the tokens should be validated.
     * In our case this is the authservice, which is routed through Zuul via the application.properties.
     */
    @Primary
    @Bean
    public RemoteTokenServices tokenServices() {
        final RemoteTokenServices tokenService = new RemoteTokenServices();
        tokenService.setCheckTokenEndpointUrl(tokenUrl);
        tokenService.setClientId(clientId);
        tokenService.setClientSecret(clientSecret);
        return tokenService;
    }
}

What I've tried is using this filter in the Gateway:

    @Bean
    SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) throws Exception {
        return http
                .csrf().disable()
                .authorizeExchange()
                .pathMatchers("/oauth/**")
                .permitAll()
                .and()
                .authorizeExchange()
                .pathMatchers("/users/**")
                .authenticated()
                .anyExchange().permitAll()
                .and()
                .build();
    }

However, when I try to access anything on the /users/ endpoint I get a 401; because the Gateway doesn't know where and how it should check the token it got.

Please note that I don't use a JWT token, but an UUID (default config I guess). The .oauth2ResourceServer().jwt() seems unapplicable because of this. I can't seem to find any useful sources as to what the .oauth2ResourceServer().bearerTokenConverter() is supposed to do, the docs don't mention it.

I want the Cloud Gateway to not think about it, and just send a request to the authservice to verify the token. I've tried to copy the aforementioned RemoteTokenService config, but this throws me into a dependency hell that I cant figure my way out of.

How can I configure the Gateway to use my own authorization server?

Note: This is a school project, so 100% production security isn't relevant.

MagicLegend
  • 328
  • 1
  • 5
  • 22

0 Answers0