Context
How has this issue affected you? I would end up DDOS the token provider service
What are you trying to accomplish? I hope to be able to cache the token based on a custom configurable TTL
What other alternatives have you considered? Are you aware of any workarounds? Not that I am aware of, but please let me know
I have a straighfoward code such as:
spring:
application:
name: client-application
security:
oauth2:
client:
registration:
hello-client:
provider: hello-provider
client-id: someusername
client-secret: somepassword
authorization-grant-type: client_credentials
scope: resolve
hi-client:
provider: hi-provider
client-id: anotherusername
client-secret: anotherpassword
authorization-grant-type: client_credentials
scope: download
provider:
hello-provider:
token-uri: https://tokenprovider.com/token
hi-provider:
token-uri: https://secureservice.com/token
application:
url:
hello: https://somecoolcompany.com/api/v1.0/hello
hi: https://veryawsomeendpoint.com/v2/hi
@Service
public class HelloServiceClient {
private static final Logger log = LoggerFactory.getLogger(HelloServiceClient.class);
private final RestClient restClient;
public HelloServiceClient(RestClient.Builder builder, @Value("${application.url.hello}") String urlHello) {
this.restClient = builder
.baseUrl(urlHello)
.requestInterceptor(
(request, body, execution) -> {
log.info("Lambda Interceptor: modifying before sending request");
ClientHttpResponse response = execution.execute(request, body);
log.info("Lambda Interceptor: modifying after receiving response");
return response;
}
)
.build();
}
public String hello() {
return this.restClient.get()
.uri("/hello")
.attributes(clientRegistrationId("hello-client"))
.retrieve()
.body(String.class);
}
}
package vn.cloud.restclientdemo.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
import static org.springframework.security.oauth2.client.web.client.RequestAttributeClientRegistrationIdResolver.clientRegistrationId;
@Service
public class HiServiceClient {
private final RestClient restClient;
public HiServiceClient(RestClient.Builder builder, @Value("${application.url.hi}") String urlHi) {
this.restClient = builder
.baseUrl(urlHi)
.build();
}
public String hi() {
return this.restClient.get()
.uri("/hi")
.attributes(clientRegistrationId("hi-client"))
.retrieve()
.body(String.class);
}
}
Please note there are 4 different URLs here
The business logic is simple, call an endpoint A, but this endpoint A needs a token from token provider B. Then call a resource endpoint C, which also needs another token from token provider D. 4 in total.
The app in under high load. And the token policies are different. For instance, the first token is valid 9 minutes, while the second token is valid only 30 seconds. Caching here is crucial, since under high load, we would like to avoid making unnecessary requests to get a token while it is still active. It would be great to cache it.
But not only to cache it, it would be amazing if we could configure the cache time.
Expected Behavior
Something like this would be great:
spring:
application:
name: client-application
security:
oauth2:
client:
registration:
hello-client:
provider: hello-provider
client-id: someusername
client-secret: somepassword
authorization-grant-type: client_credentials
scope: resolve
TTL: 100000s
hi-client:
provider: hi-provider
client-id: anotherusername
client-secret: anotherpassword
authorization-grant-type: client_credentials
scope: download
TTL: 50s
provider:
hello-provider:
token-uri: https://tokenprovider.com/token
hi-provider:
token-uri: https://secureservice.com/token
application:
url:
hello: https://somecoolcompany.com/api/v1.0/hello
hi: https://veryawsomeendpoint.com/v2/hi
Current Behavior
This is strange, since many token provider works on their own token "alive" time As of now, it seems there are no easy ways to configure custom TTL.
Would it be possible to get some help on that?
Thank you
Comment From: sjohnr
@patpatpat123 thanks for reaching out!
In your examples, I'm not seeing you apply the OAuth2ClientHttpRequestInterceptor as an interceptor per the example in the docs. Given that, any functionality provided by the interceptor and the underlying component OAuth2AuthorizedClientManager is not involved.
Caching here is crucial, since under high load, we would like to avoid making unnecessary requests to get a token while it is still active. It would be great to cache it.
"Caching" as you describe it is provided by the underlying components in Spring Security, namely an OAuth2AuthorizedClientRepository and I can't tell if you're using them as per the documentation. The feature you're requesting here is already supported.
But not only to cache it, it would be amazing if we could configure the cache time.
This request is contrary to the core OAuth 2.0 spec, Section 4.1.4 which specifies that the expiration time for a token is provided in the Access Token Response. Handling token refresh or new access token requests (for client_credentials grant) using a clock skew (default is 60 seconds) is also already supported. If you have a requirement for a custom TTL, it would then need to be handled through customization.
Since it appears that you are not yet configuring and using the existing features according to the documentation, please give that a try. I am going to close this issue. If you have further questions, please provide a link to a stack overflow question an I'll be happy to help. If I have misunderstood anything, please let me know.