Skip to content

Unable to configure client_assertion_type with private_key_jwt for client credential grant type #11181

@mit2222

Description

@mit2222

Describe the bug
I am using spring-boot-starter-parent 2.6.4. I need to integrate with Okta api with client credentials private_key_jwt. Okta's /v1/token url needs client_assertion_type of urn:ietf:params:oauth:client-assertion-type:jwt-bearer, grant type as client_credentials and authentication method as PRIVATE_KEY_JWT.

Expected behavior
I would like to retrieve access token via client_credentials private_key_jwt flow through Spring Boot WebClient in-memory solution.

To Reproduce
I have the below bean configurations. However, v1/token url never gets called. I think the issue with client_assertion_type urn:ietf:params:oauth:client-assertion-type:jwt-bearer along with clientAuthenticationMethod as PRIVATE_KEY_JWT for grant type as client_credentials.


 @Bean
    ReactiveClientRegistrationRepository clientRegistrations() {

        ClientRegistration registration = ClientRegistration
                .withRegistrationId("OktaExample")
                .tokenUri("https://{oktaDomain}/oauth2/v1/token")
                .clientId(clientId)
                .clientAuthenticationMethod(ClientAuthenticationMethod.PRIVATE_KEY_JWT)
                .scope(scope)
                .authorizationGrantType(new AuthorizationGrantType("urn:ietf:params:oauth:client-assertion-type:jwt-bearer"))
                .build();
        return new InMemoryReactiveClientRegistrationRepository(registration);
    }


    @Bean
    public ReactiveOAuth2AuthorizedClientService authorizedClientService(
            ReactiveClientRegistrationRepository clientRegistrations) {
        return new InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrations);
    }
    @Bean
    public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
            ReactiveClientRegistrationRepository clientRegistrations,
            ReactiveOAuth2AuthorizedClientService authorizedClientService) {
        return configureHttpProxy(
                new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
                        clientRegistrations,
                        authorizedClientService
                ));
    }

  private AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager configureHttpProxy(AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
        
        Function<ClientRegistration, JWK> jwkResolver = client -> {
                // Assuming RSA key type
                return new RSAKey.Builder(publicKey)
                        .privateKey(privateKey)
                        .keyID(UUID.randomUUID().toString())
                        .build();
        };

        // set the webclient with proxy configuration in the ReactiveOAuth2AccessTokenResponseClient
        WebClientReactiveClientCredentialsTokenResponseClient tokenResponseClient = new WebClientReactiveClientCredentialsTokenResponseClient();
        tokenResponseClient.addParametersConverter(new NimbusJwtClientAuthenticationParametersConverter<>(jwkResolver));

        tokenResponseClient.setWebClient(
                WebClient.builder().build()
        );

        ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider= ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
                .clientCredentials(clientCredentialsGrantBuilder ->
                        clientCredentialsGrantBuilder.accessTokenResponseClient(tokenResponseClient)) 
                .build();


        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

        return authorizedClientManager;
    }
   @Bean
    WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
                

       ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
        oauth2Client.setDefaultClientRegistrationId("OktaExample");

        return WebClient.builder()
                .filters(exchangeFilterFunctions -> {
                    exchangeFilterFunctions.add(oauth2Client);
                })
                .build();
    }

Metadata

Metadata

Assignees

Labels

in: oauth2An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose)status: invalidAn issue that we don't feel is valid

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions