Spring Cloud Gateway - opaque tokens

Viewed 1098

I'm currently looking at implementing an API Gateway using Spring Cloud Gateway. There will be some React clients to the APIs and also some devices. The devices will be granted access using OAuth device_code grant. The API gateway will pass JWT to back end resource API servers, which will validate the request. I have followed the following example which seems to get me part of the way there.

https://spring.io/blog/2019/08/16/securing-services-with-spring-cloud-gateway I've also been able to swap out the IdP in that example for WSO2.

I obtained a bearer token from the IdP using curl in order to test using an opaque token.

curl -u OzVconnyapPW2yWzxrSebCKmY9Qa:5cBcZmnnaW5gGOW3qt9sumw4Ubka -k -d "grant_type=password&username=admin&password=admin" -H "Content-Type:application/x-www-form-urlencoded" https://localhost:9443/oauth2/token

which returned me an access token.

curl -k http://springboot.example.com:8080/ -H "Authorization: Bearer 123b546d-f35b-38b8-a2c8-4e0d4487329d"

But this tries to redirect me to login.

How can I get Spring Cloud API Gateway to process requests where an Authorization: Bearer xxxx header has been added? Am I using the correct 'opaque token' (i.e. is an Authorization token the correct way to do this)? Can the oauth2 client be bypassed if an Authorization header is set and could a resource server be triggered instead?

This diagram represents my current thinking, which could be wrong (please say if so!) API Design

API Gateway app:

package com.scg.gateway;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.cloud.security.oauth2.gateway.TokenRelayGatewayFilterFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.annotation.RegisteredOAuth2AuthorizedClient;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
@SpringBootApplication
public class GatewayApplication {

    @Autowired
    private TokenRelayGatewayFilterFactory filterFactory;

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("resource", r -> r.path("/resource")
                    .filters(f -> f.filters(filterFactory.apply())

                                    .removeRequestHeader("Cookie")) // Prevents cookie being sent downstream
                    .uri("http://springboot.example.com:9000")) // Taking advantage of docker naming
                .build();
    }

    @GetMapping("/")
    public String index(Model model,
                        @RegisteredOAuth2AuthorizedClient OAuth2AuthorizedClient authorizedClient,
                        @AuthenticationPrincipal OAuth2User oauth2User) {
        model.addAttribute("userName", oauth2User.getName());
        model.addAttribute("clientName", authorizedClient.getClientRegistration().getClientName());
        model.addAttribute("userAttributes", oauth2User.getAttributes());
        return "index";
    }

    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

API Gateway Yaml

server:
  port: 8080

logging:
  level:
    root: INFO
    org.springframework.web: INFO
    org.springframework.web.HttpLogging: DEBUG
    org.springframework.security: DEBUG
    org.springframework.security.oauth2: DEBUG
    org.springframework.cloud.gateway: DEBUG

spring:
  autoconfigure:
    # TODO: remove when fixed https://github.com/spring-projects/spring-security/issues/6314
    exclude: org.springframework.boot.actuate.autoconfigure.security.reactive.ReactiveManagementWebSecurityAutoConfiguration
  thymeleaf:
    cache: false
  security:
    oauth2:
      client:
        registration:
          gateway:
            provider: wso2
            client-id: OzVconnyapPW2yWzxrSebCKmY9Qa
            client-secret: 5cBcZmnnaW5gGOW3qt9sumw4Ubka
            authorization-grant-type: authorization_code
            redirect-uri-template: "{baseUrl}/login/oauth2/code/wso2"
            scope: openid,profile,email,resource.read
        provider:
          wso2:
            authorization-uri: http://idp.example.com:9763/oauth2/authorize
            token-uri: http://idp.example.com:9763/oauth2/token
            user-info-uri: http://idp.example.com:9763/oauth2/userinfo
            user-name-attribute: sub
            jwk-set-uri: http://idp.example.com:9763/oauth2/jwks
0 Answers
Related