Expected Behavior
When using RestClient with OAuth2ClientHttpRequestInterceptor, there should be a public constant available for the client registration ID attribute name, similar to other OAuth2-related constants in Spring Security. This would allow developers to reliably reference this attribute name without having to reconstruct it manually.
Current Behavior
Currently, developers must manually construct the attribute name by concatenating the RequestAttributeClientRegistrationIdResolver class name with ".clientRegistrationId". This is fragile as it relies on internal implementation details that could change:
@Bean("my-client-rest-client")
fun restClient(
authorizedClientManager: OAuth2AuthorizedClientManager,
serviceConfiguration: ServiceConfiguration,
): RestClient {
val requestInterceptor = OAuth2ClientHttpRequestInterceptor(authorizedClientManager)
val clientRegistrationIdAttributeName =
"${RequestAttributeClientRegistrationIdResolver::class.java.name}.clientRegistrationId"
return RestClient.builder()
.requestInterceptor(requestInterceptor)
.defaultRequest { requestSpec ->
requestSpec.attribute(clientRegistrationIdAttributeName, "my-client")
}
.baseUrl("https://api.example.com")
.build()
}
Context
This issue affects developers integrating OAuth2 client credentials flow with Spring's new RestClient. The current approach of manually constructing the attribute name:
- Is prone to breaking if Spring's internal implementation changes
- Requires developers to understand Spring Security's internal implementation details
- Creates maintenance overhead when upgrading Spring versions
- Goes against Spring's typical approach of providing public constants for such values
Considered alternatives:
- Creating a custom constant in application code (still requires maintenance)
- Using WebClient instead (not always feasible when RestClient is preferred)
Current workaround is the manual string construction shown above, but this is not ideal for production code. Spring Boot version: 3.4.0 Spring Security version: 6.4.1
Comment From: SuveenVundavalli
Oh, we can use the RequestAttributeClientRegistrationIdResolver.clientRegistrationId method to add this. This is no longer required. Did something like:
@Bean("my-client-rest-client")
fun restClient(
authorizedClientManager: OAuth2AuthorizedClientManager,
serviceConfiguration: ServiceConfiguration,
): RestClient {
val requestInterceptor = OAuth2ClientHttpRequestInterceptor(authorizedClientManager)
return RestClient.builder()
.requestInterceptor(requestInterceptor)
.defaultRequest { requestSpec ->
requestSpec.attributes(
RequestAttributeClientRegistrationIdResolver.clientRegistrationId("my-client"))
}
.baseUrl("https://api.example.com")
.build()
}