Skip to content

Simplify configuration of OAuth2 Client component model #11783

Closed
@wujek-srujek

Description

@wujek-srujek

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?

Metadata

Metadata

Assignees

Labels

in: oauth2An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose)theme: partner-use-casesUse cases we identified with a partner (an established contributor)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions