Description
Expected Behavior
I would like an easy way to add custom parameters for authorization and token requests.
Current Behavior
Currently it is possible but very difficult and verbose. It is also documented badly without a single example, e.g. https://docs.spring.io/spring-security/reference/servlet/oauth2/client/authorization-grants.html#oauth2Client-client-creds-grant only says what to do (more or less) but the whole page is missing examples.
Context
A similar issue is #7379.
I am using Auth0 which requires a custom request parameter audience
for the client_credentials
grant. It is currently possible but very hard (it took me some time to figure out what to do, and I'm not even sure if this is correct, but it works) and verbose to add this parameter with Spring Security:
val converter = OAuth2ClientCredentialsGrantRequestEntityConverter()
converter.addParametersConverter {
LinkedMultiValueMap<String, String>().apply {
this["audience"] = "xyz_value" // <=== All I want to do is this.
}
}
val client = DefaultClientCredentialsTokenResponseClient()
client.setRequestEntityConverter(converter)
val clientProvider = OAuth2AuthorizedClientProviderBuilder
.builder()
.clientCredentials { it.accessTokenResponseClient(client) }
.build()
val manager = DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository,
)
manager.setAuthorizedClientProvider(clientProvider)
val filter = ServletOAuth2AuthorizedClientExchangeFilterFunction(manager)
The only real valuable change is one line which adds the parameter, but to make it work I need to add a lot of code around it. The written code is pretty much a copy of what Spring Security would do itself. However, I don't even think the code above is equivalent to creating a ServletOAuth2AuthorizedClientExchangeFilterFunction
with a ClientRegistrationRepository
and OAuth2AuthorizedClientRepository
as that constructor also sets up an AuthorizationFailureForwarder
, which my code doesn't. If I wanted to also do that I would need to copy even more code from the depths of Spring Security.
The difficulty seems to stem from the fact that all of the objects needed are instantiated internally and not dependency injected. For example, the ServletOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrationRepository, authorizedClientRepository)
constructor internally creates an DefaultOAuth2AuthorizedClientManager
with all the possible clients, but it is impossible to change them in any way, without pretty much rebuilding everything on my own.
(If I'm wrong and it is indeed possible, awesome, please show me how to limit the amount of code above.)
I'm thinking about making it possible to define a OAuth2ClientCredentialsGrantRequestEntityConverter
@Bean
whose instances would be looked up and applied when a request is built. Or maybe even just the 'parametersConverters', which are @Ordered
and lookup up and applied?