How to Use Client Credentials Flow with Spring Security

Would this remain the recommended approach if attempting to write a custom PropertySourceLocator in spring boot 2.6.X? I’m attempting to follow this: spring-cloud-config-issue-177 but a lot of the examples are dated. I would like to use the reactive approach if possible.

@Btpowell3 Looks like you may have posted to the wrong thread?
Is your question related to config properties for a Client Credentials flow?

Hello. I am using webcilent (org.springframework.web.reactive.function.client.WebClient). I am getting connection reset by peer when I make a call to https://domain}/oauth2/default/v1/token for client credentials grant type with client id and secret ie with header as Authorization Basic {Base 64 clientId:clientsecret}
I am able to use POST call to https://domain}/oauth2/default/v1/token via rest template and I get an access token

Not sure that this will help, but we do have a post about WebClient.

Thank you I was able to solve the issue with webclient. I am trying to configure private_key_jwt with client_assertion_type as urn:ietf:params:oauth:client-assertion-type:jwt-bearer through webclient in memory in order to integrate with okta users api. Currrently my webclient is configured with client_secret_basic authentication (client credentials) mechanism and I get http 400 when I integrate with okta users api. I am using spring boot parent 2.6.x and spring security 5.6.x.

Hi @vdc305!

I’m not sure I understand the question.

Are you looking for information on calling Okta’s API using a scoped OAuth token?

If so, you will need to change your issuer to https://{domain} (dropping the /oauth/default part).

If that isn’t what you are looking for let us know!

Is there a way to integrate with Okta users api with client_secret_basic authentication (client credentials) mechanism ? I get the access token from client_secret_basic authentication via /oauth2/default/token. However, I get 400 when I use the access token as Authorization Bearer token to integrate with Okta users api. I am able to call users api with SSWS but I would like to use client credentials by leveraging Spring boot webclient

Yes, but I think you might be mixing concerns.

Okta has two different types of Authorization Servers (issuers).

TL;DR

  1. “Org level” - This allows you to log into Okta’s applications (admin console, user dashboard) and call Okta’s APIs
  2. “Custom” Authorization Server - If you are building your own APIs and need custom scopes and attributes this is what you want.

To call Okta’s APIs you would need an access token from the first one.

Since you are asking this question in a “Client Credentials” post I’m assuming you do NOT have a user in the context of your request. If this is the case I’d recommend using the Okta Management SDK: GitHub - okta/okta-sdk-java

That said, if you want to build the request yourself you can just follow this guide:

Yes, my request doesnt have a user context. I want to use Okta user api for eg: update a lifecycle. I have integrated it through SSWS or client credentials signed jwt. If I want to use client_credentials to call Okta user api I think I need to use “Org level” option via client credentials private_key_jwt. Also, the guide you provided which is client_credentials with private_key_jwt works fine with Spring boot RestTemplate but not through Spring Boot webclient. I will try Okta GitHub - okta/okta-sdk-java.

Because client_credentials with private_key_jwt wasn’t working with Spring Boot WebClient I thought of using client_credentials with clientId and secret to get access token which I could then use it to call Okta user api (to update a lifecycle for the pertaining Okta ID (userID in Okta) but I get 400 .

So it makes sense if I have my own api I can get access token with custom scopes to integrate with via client_credentials through `client authentication methods but if I need to call Okta api ie “Org level” then SSWS and client_credentials with private_key_jwt

You won’t need an SSWS token if you use the private_key_jwt option. The SDK will do all of this for you. You just need to supply the key.

Sure I will try out private_key_jwt with okta sdk. I am hoping the clients.builder can be used to udpate lifecycle, user profile and credentials.

But I would also like to implement private_key_jwt in spring boot without okta sdk and I am having issues with webclient in-memory. Simple webclient with signed JWT works but I would like to have in-memory solution too.

Can you describe what you mean by the in-memory issues with webclient?

I have opened a git issue Unable to configure client_assertion_type with private_key_jwt for client credential grant type · Issue #11181 · spring-projects/spring-security · GitHub. We already have code base with private_key_jwt but without in-memory and I thought in-memory solution with webclient would be good so that we dont have to call Okta to get the access token for all the calls to Okta user api.

Also, I tried okta-sdk-java and I was able to configure privatee_key_jwt and call okta users api. Also do you have an example of exception handling ?


    Client client = Clients.builder()
                .setOrgUrl("{domain}")
                .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY)
                .setClientId(clientId)
                .setScopes(new HashSet<>(Arrays.asList(scope)))
                .setPrivateKey(getPrivateKey())
                .build();

        UserList users = client.listUsers("john.doe@someemail.com", null, null, null, null);

Also, is there a way to cache access token retrieved from private_key_jwt client_credentials grant type ?

I have the below code configured for private_key_jwt in regards to caching.

 CacheManager cacheManager = Caches.newCacheManager()
                .withDefaultTimeToLive(300, TimeUnit.SECONDS) // default
                .withDefaultTimeToIdle(300, TimeUnit.SECONDS) //general default
                .withCache(forResource(User.class) //User-specific cache settings
                        .withTimeToLive(1, TimeUnit.HOURS)
                        .withTimeToIdle(30, TimeUnit.MINUTES))
                .withCache(named("OAuth2AccessToken") //this didnt work
                        .withTimeToLive(1, TimeUnit.HOURS))
                .build();

      Client client = Clients.builder()
                .setOrgUrl("{domain}")
                .setAuthorizationMode(AuthorizationMode.PRIVATE_KEY)
                .setClientId(clientId)
                .setScopes(new HashSet<>(Arrays.asList(scope)))
                .setPrivateKey(getPrivateKey())
                .setCacheManager(cacheManager)
                .build();

Hey @vdc305!

Sorry for the delay!

The exceptions thrown by the Okta Java SDK are typically all runtime exceptions. You can catch ResourceException and call getError() to see what the actual error payload returned from Okta was:
https://developer.okta.com/okta-sdk-java/development/apidocs/com/okta/sdk/resource/ResourceException.html

For caching, I’m not sure I understand the question, but I’ll take a shot at it and let me know if I’ve answered your question or not :wink:

If you are already in the Spring world, you can use Spring Cache with the Okta Java SDK: GitHub - okta/okta-spring-boot: Okta Spring Boot Starter

Or if you are creating the Client object, you could use the following Okta SDK cache impl:

For caching the access token that is used by the SDK, you shouldn’t need to configure anything at all. The SDK will store it’s access token and refresh it as needed.

NOTE: how long your access token is active is a server configuration and can be configured via the Okta Admin Console (or equivalent API).

The Client object should be treated as a singleton (or equivalent in your application).

Let us know if this helps!

Thanks. I will look into solution for caching via okta sdk as well. I went with spring security and configured access token retrieved from Okta via client credentials signed jwt into in-memory cache.
I had also reached out to spring security community since custom configuration is needed for signed jwt due to client_assertion_type

1 Like

Hi, It was a nice article and useful. One question, why a resource server need to configure with client-id, cliend-secret as properties? Scope of resource server is to get protected with Auth server and client scope is to access resource server using access token. In that case why resource server need to configure with client registration info? Please correct my understanding in case i am wrong.

Hey @rajivgudipati

The resource server would (remotely) authenticate with the Issuer of the access token using the client ID and secret when it validates the token. This isn’t needed if you are application is using JWT access tokens, where the token is just validated locally.

Thank you @bdemers . Appretiate for quick response.
One more question w.r.t OAuthClientConfiguration, in the article it was mentioned as “In the context of a servlet, much of what this file does would be accomplished automatically by Spring auto-configuration.”
Since it is command line utility did we create all the client related stuff, if not what couble be the better way to use auto-configuration? Do you have any example or reference for servlet based implementation.

@bdemers Thanks for great examples. I have observed two issues with this example of Client credentials flow

  • The Resource server does not make use of okta.oauth2.client-secret and okta.oauth2.client-id defined in properties file. All it need is okta.oauth2.issuer to download the okta public keys and validate the token. I also looked at Spring Security documentation and there is no need to define client secrets in properties file of resource server.
    OAuth 2.0 Resource Server JWT :: Spring Security

  • I registered two different applications on Okta portal and both of them are able to access this resource server as long as they pass mod_custom scope while requesting token. There is no direct mapping between scope and application.
    How do I overcome this limitation ? Shall I create a Custom Authorization Server dedicated to my application ( and Map it to app under policies) and define scopes there ? And also configure resource server as per custom auth server?

Thanks in Advance.