Context
Front end app with PKCE accessing a resource server with both local and remote token validation enabled in the Security Configuration. I'm following the advice based on this article
Current Behavior
NimbusOpaqueTokenIntrospector expects a client secret besides a client id and an introspection uri for remote token validation in one of it's constructors. Apps with PKCE enabled don't have client secret and it results getting clientSecret cannot be null when used. With the 2nd constructor (introspection uri and rest template), 400 Bad Request: invalid_client, client_id must be provided in the request error gets thrown during validation.
Is there a way for a resource server to use opaque token introspection with PKCE enabled on the front end?
Expected Behavior
The IdP that I use provides the remote introspection through the same endpoint with client-id as a query parameter. I'm not sure every IdP follows the same procedure. If so, could we have the logic incorporated into NimbusOpaqueTokenIntrospector?
At the moment I'm using a Custom class based on NimbusOpaqueTokenIntrospector with an additional logic for building token introspection URI without client-secret. The URI generation logic is provided below,
private URI buildIntrospectionUri(String introspectionUri, String clientId) {
UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(introspectionUri)
.queryParam("client_id", clientId);
return URI.create(builder.toUriString());
}
Comment From: jzheaux
Hi, @vivekworks, thanks for the suggestion.
The introspection RFC requires some form of authorization to make the request:
To prevent token scanning attacks, the endpoint MUST also require some form of authorization to access this endpoint, such as client authentication as described in OAuth 2.0 [RFC6749] or a separate OAuth 2.0 access token such as the bearer token described in OAuth 2.0 Bearer Token Usage [RFC6750].
Just handing over a client_id is not a form of authorization, so I don't think this should be added to NimbusOpaqueTokenIntrospector.
To add your own authorization mechanism, it's recommended that you configure a RestTemplate with your own custom interceptor, instead of using the default BasicAuthorizationInterceptor.
Then you can do:
@Bean
OpaqueTokenIntrospector opaqueTokenIntrospector() {
RestTemplate rest = new RestTemplate();
rest.getInterceptors().add(new MyCustomAuthorizationInterceptor());
return new NimbusOpaqueTokenIntrospector(uri, rest);
}
What's nice about this approach is that you won't need to create a custom opaque token introspector.
Comment From: vivekworks
@jzheaux Thank you for your suggestion. I'll try it out.
Update:
It worked with a custom ClientHttpRequestInterceptor for RestTemplate. Thank you for the support @jzheaux