Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TokenRelay bug when using different oauth2 client registration #3535

Open
rpapeters opened this issue Sep 21, 2024 · 1 comment
Open

TokenRelay bug when using different oauth2 client registration #3535

rpapeters opened this issue Sep 21, 2024 · 1 comment

Comments

@rpapeters
Copy link

spring-cloud-starter-gateway v4.1.5

When using a different client registration for the TokenRelay filter (like TokenRelay=someClientRegistrationId and not the one used for logging in the user), the Bearer auth header is not set. I think this is because the client used for the TokenRelay does not get an authorizedClient.

Example application security config:

  security:
    oauth2:
      client:
        provider:
          myAuthProvider:
            issuer-uri: ${issuerUri}
            user-name-attribute: name
        registration:
          loginClient:
            provider: myAuthProvider
            authorization-grant-type: authorization_code
            client-id: ${clientId}
            client-secret: ${clientSecret}
            scope: openid,profile,email,offline_access
          resourceClient:
            provider: myAuthProvider
            authorization-grant-type: client_credentials
            client-id: ${clientId}
            client-secret: ${clientSecret}
            scope: /.default
  cloud:
    gateway:
      routes:
        - id: resourceServerRoute
          uri: ${resouceServerUri}
          predicates:
            - Path=/resource/**
          filters:
            - TokenRelay=resourceClient

Suggested solution (inspired by https://docs.spring.io/spring-security/reference/reactive/oauth2/client/authorization-grants.html#_using_the_access_token):

In function TokenRelayGatewayFilterFactory.authorizationRequest add .attribute(ServerWebExchange.class.getName(), exchange) to the builder like so:

    private Mono<OAuth2AuthorizeRequest> authorizationRequest(String defaultClientRegistrationId,
                                                              Authentication principal,
                                                              ServerWebExchange exchange) {
        String clientRegistrationId = defaultClientRegistrationId;
        if (clientRegistrationId == null && principal instanceof OAuth2AuthenticationToken) {
            clientRegistrationId = ((OAuth2AuthenticationToken) principal).getAuthorizedClientRegistrationId();
        }
        return Mono.justOrEmpty(clientRegistrationId).map(OAuth2AuthorizeRequest::withClientRegistrationId)
                .map(builder -> builder.principal(principal).attribute(ServerWebExchange.class.getName(), exchange).build());
    }

@rpapeters rpapeters changed the title TokeRelay bug when using different oauth2 client registration TokenRelay bug when using different oauth2 client registration Sep 21, 2024
@rpapeters
Copy link
Author

So I was having multiple moving parts when I was trying to solve this issue, and now looking into it a bit further after a good night sleep the suggested solution in my first post is actually not what solved the issue. The other thing I changed was adding explicit security config and adding the clientCredentials as provider, see code below:

@Configuration
@EnableWebFluxSecurity
public class SecurityConfig {

    @Bean
    public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
            ReactiveClientRegistrationRepository clientRegistrationRepository,
            ServerOAuth2AuthorizedClientRepository authorizedClientRepository) {

        ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
                ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
                        .authorizationCode()
                        .clientCredentials()
                        .build();

        DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager =
                new DefaultReactiveOAuth2AuthorizedClientManager(
                        clientRegistrationRepository, authorizedClientRepository);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

        return authorizedClientManager;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant