Skip to content

Use AuthorizedClientServiceOAuth2AuthorizedClientManager for client_credentials #283

@xehpuk

Description

@xehpuk

I currently have two client registrations with a rest client each:

spring:
  security:
    oauth2:
      client:
        provider:
          keycloak:
            issuer-uri: ${keycloak-configuration.issuer-uri}
        registration:
          keycloak-authorization-code:
            provider: keycloak
            authorization-grant-type: authorization_code
            client-id: ${keycloak-configuration.client-id}
            client-secret: ${keycloak-configuration.client-secret}
            scope:
              - openid
          keycloak-client-credentials:
            provider: keycloak
            authorization-grant-type: client_credentials
            client-id: ${keycloak-configuration.client-id}
            client-secret: ${keycloak-configuration.client-secret}
com:
  c4-soft:
    springaddons:
      rest:
        client:
          foo-client:
            base-url: ${foo-service.base-url}
            authorization:
              oauth2:
                oauth2-registration-id: keycloak-authorization-code
          bar-client:
            base-url: ${bar-service.base-url}
            authorization:
              oauth2:
                oauth2-registration-id: keycloak-client-credentials
            expose-builder: true

For my bar-client to work, I have to use the Builder to change the OAuth2AuthorizedClientManager from DefaultOAuth2AuthorizedClientManager to AuthorizedClientServiceOAuth2AuthorizedClientManager (it's used in a background thread). But then I lose the ClientRegistrationIdResolver you create in the RestClientBuilderFactoryBean, so the two options I currently see are:

@Bean
fun barClient(
    barClientBuilder: RestClient.Builder,
    clientRegistrationRepository: ClientRegistrationRepository,
    authorizedClientService: OAuth2AuthorizedClientService,
    oauth2AuthorizedClientProvider: OAuth2AuthorizedClientProvider,
): RestClient = barClientBuilder.requestInterceptors {
    it.clear()
    it.add(
        OAuth2ClientHttpRequestInterceptor(
            AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService).apply {
                setAuthorizedClientProvider(oauth2AuthorizedClientProvider)
            }
        ).apply {
            // option 1
            setClientRegistrationIdResolver {
                "keycloak-client-credentials"
            }
        })
}.requestInitializer { request ->
    // option 2
    RequestAttributeClientRegistrationIdResolver.clientRegistrationId("keycloak-client-credentials").accept(request.attributes)
}.build()
  1. Overwrite the ClientRegistrationIdResolver in the OAuth2ClientHttpRequestInterceptor with a custom one.
  2. Add a ClientHttpRequestInitializer to let the default RequestAttributeClientRegistrationIdResolver get the registration ID from the request attributes.

With both options, I have to reconfigure the registration ID, even though it's already configured in the application properties. Is there a better option I'm missing?

Either way, if the AuthorizedClientServiceOAuth2AuthorizedClientManager was the default for client_credentials clients, it would work out of the box.

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions