spring-cloud / spring-cloud/spring-cloud-gateway

Could i use TokenRelay Filter with grant-type: client_credentials

Open
#3,508 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

waiting-for-triage
Dominant language
Java
Stars
4.9k
Forks
3.5k
Avg merge
20h 57m
Merged PRs (30d)
8

Description

Describe the bug
The TokenRelayFilter doesn't work with grant-type: client_credentials, the gateway doesn't retreive the access token from IDP (keycloak)

Details

In my use case the gateway should retreive the token and downstream to another (API).

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>3.0.5</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>ma.sg.df.gateway</groupId>
	<artifactId>partner</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>partner</name>
	<description>Gateway partner zone</description>
	<properties>
		<java.version>17</java.version>
		<spring-cloud.version>2022.0.3</spring-cloud.version>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-gateway</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-oauth2-client</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>org.springframework.cloud</groupId>
				<artifactId>spring-cloud-dependencies</artifactId>
				<version>${spring-cloud.version}</version>
				<type>pom</type>
				<scope>import</scope>
			</dependency>
		</dependencies>
	</dependencyManagement>
</project>

application.yml

spring:
  application:
    name: Partner Gateway
  cloud:
    gateway:
      routes:
        - id: card
          uri: https://test.net/api/trans
          predicates:
            - Path=/api/trans/**
          filters:
            - TokenRelay=ocidp
  security:
    oauth2:
      client:
        registration:
          ocidp:
            authorization-grant-type: client_credentials
            client-id: test
            client-secret: 548dRRRRRR7
        provider:
          ocidp:
            token-uri: https://test.net/auth/realms/realm-api/protocol/openid-connect/token

SecurityConfig class

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {


	@Bean
	SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http) {
		http
				// ...
				.csrf(ServerHttpSecurity.CsrfSpec::disable)
				.authorizeExchange((authorize) -> authorize
								.pathMatchers("/api/trans/**")
								.permitAll()
								.anyExchange()
								.authenticated()).oauth2Client(Customizer.withDefaults());

		return http.build(); 
     }
}

When i call the api through the gateway have 401 http error

When I launch the debug in the class TokenRelayGatewayFilterFactory can't cast(OAuth2AuthenticationToken.class)

	public GatewayFilter apply(Object config) {
		return (exchange, chain) -> exchange.getPrincipal()
				// .log("token-relay-filter")
				.filter(principal -> principal instanceof OAuth2AuthenticationToken)
				.cast(OAuth2AuthenticationToken.class)
				.flatMap(authentication -> authorizedClient(exchange, authentication))
				.map(OAuth2AuthorizedClient::getAccessToken).map(token -> withBearerAuth(exchange, token))
				// TODO: adjustable behavior if empty
				.defaultIfEmpty(exchange).flatMap(chain::filter);
	}

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with TokenRelayGatewayFilterFactory and the OAuth2 client configuration shown in application.yml, then compare how the filter obtains a principal for client_credentials. Review SecurityConfig and the reported cast failure; done means the gateway retrieves the IDP access token and relays it to the downstream API without the 401 response.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring, spring-boot
Domain
api, authentication
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.