I'm new on OAuth2 and Spring Cloud Gateway(And WebFlux things).

My team decided to move from Zuul gateway to Spring Cloud Gateway. And current Spring Cloud version is "Greenwich.SR1"

The problem is spring cloud gateway always response 401.

How to pass access token on Spring Cloud Gateway properly?

Auth server :

@EnableEurekaClient
@EnableAuthorizationServer
@SpringBootApplication
public class AuthServer {...} // jwtAccessTokenConverter bean included

Zuul server is :

@EnableEurekaClient
@EnableZuulProxy
@SpringBootApplication
public class ZuulServer {...}

Zuul server properties :

zuul:
  sensitive-headers: Cookie,Set-Cookie
  ignored-services: '*'
  routes:
    auth: /auth/**

Spring Cloud Gateway Server properties :

spring:
  cloud:
    gateway:
      routes:
        - id: auth
          uri: lb://auth
          predicates:
            - Method=POST
            - Path=/auth/**
          filters:
            - RemoveRequestHeader= Cookie,Set-Cookie
            - StripPrefix=1

Spring Cloud server build.gradle :

plugins {
    id 'java'
    id "io.freefair.lombok" version "3.2.0"
    id "org.springframework.boot" version "2.1.5.RELEASE"
    id "io.spring.dependency-management" version "1.0.6.RELEASE"
}

version = '1.0.0-SNAPSHOT'
description = 'edge-service2'
sourceCompatibility = '11'

dependencies {
    implementation platform("org.springframework.cloud:spring-cloud-dependencies:$springCloudVersion")
    implementation "org.springframework.boot:spring-boot-starter-security"
    implementation "org.springframework.cloud:spring-cloud-starter-netflix-eureka-client"
    implementation "org.springframework.cloud:spring-cloud-starter-netflix-ribbon"
    implementation "org.springframework.cloud:spring-cloud-starter-netflix-hystrix"

    implementation('org.springframework.cloud:spring-cloud-starter-gateway')

    implementation "org.springframework.cloud:spring-cloud-config-client"
    implementation "de.codecentric:spring-boot-admin-starter-client:$springBootAdminVersion"
    implementation "net.gpedro.integrations.slack:slack-webhook:1.4.0"
    testImplementation "org.springframework.boot:spring-boot-starter-test"
}


springBoot {
    buildInfo()
}

bootJar {
    archiveName "${project.name}.jar"
}

There is a feature in Spring Cloud Security for relaying the access token to downstream services via Spring Cloud Gateway: https://cloud.spring.io/spring-cloud-static/spring-cloud-security/2.1.3.RELEASE/single/spring-cloud-security.html#_token_relay

Simply use the TokenRelay Filter for your route or default configuration. However, this forwards just the access token. "The access token is the artifact that allows the client application to access the user's resource"[1], whereas "an ID token is an artifact that proves that the user has been authenticated"[1], and it also contains the user attributes.

It seems that's what you want anyway, but for all the people out there that use OIDC and want to relay the ID Token, here's some more information. Write a custom GatewayFilterFactory where you:

  • get the authenticated Principal via exchange.getPrincipal().ofType(OAuth2AuthenticationToken.class)
  • map it until you get an oAuth2User Objekt
  • cast it to an OidcUser
  • now you can do oidcUser.getIdToken.getTokenValue()
  • put it into a header of your choice and thus you can also forward the ID Token, not only the Access Token.

[1] https://auth0.com/blog/id-token-access-token-what-is-the-difference/