It would be nice to have a means to add entries or modify entries in the ClientRegistration.ProviderDetails.configurationMetadata
The method ClientRegistrations.fromOidcIssuerLocation returns a ClientRegistration.Builder which can be used to further modify the ClientRegistration. The providerConfigurationMetadata can also be overridden, but since it contains a Map, those values returned by the call to the ".well-known" endpoint will be lost.
.providerConfigurationMetadata(
Collections.singletonMap("end_session_endpoint", "https://myprovider/oidc/logout")
)
Since build() copies the values into an `unmodifiableMap', the Map also cannot be updated afterwards.
clientRegistration.getProviderDetails().getConfigurationMetadata()
.put("end_session_endpoint", "https://myprovider/oidc/logout");
....
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableMap.put(Unknown Source)
My particular use case is to be able to customize the value of the "end_session_endpoint" which is stored in the providerConfigurationMetadata, but this might also be a handy place to store custom values which otherwise would require extending ClientRegistration.
Comment From: jgrandja
@pthorson You can customize the value of the end_session_endpoint as follows:
ClientRegistration registration = ClientRegistrations.fromOidcIssuerLocation("issuer-uri").build();
Map<String, Object> configurationMetadata = registration.getProviderDetails().getConfigurationMetadata();
// TODO update value of end_session_endpoint
ClientRegistration updatedRegistration = ClientRegistration.withClientRegistration(registration)
.providerConfigurationMetadata(configurationMetadata)
.build();
NOTE: ClientRegistration.withClientRegistration(registration) is available in 5.2.0.
I'm going to close this issue as I feel I provided you a solution. We can always reopen if need be.
Comment From: pthorson
OK I was still on 5.2.0 M2. I see the new method now that I have upgraded 5.2.1.
The ClientRegistration Build still sets the Map unmodifiable in its call to create:
providerDetails.configurationMetadata = Collections.unmodifiableMap(this.configurationMetadata);
So I just have to copy it after grabbing it and then it can be modified and built again:
Map<String, Object> unmofifiableConfigurationMetadata = clientRegistration.getProviderDetails().getConfigurationMetadata();
Map<String, Object> configurationMetadata = new HashMap<>(unmofifiableConfigurationMetadata);
configurationMetadata.put("end_session_endpoint", "my_uri");
ClientRegistration updatedRegistration = ClientRegistration.withClientRegistration(clientRegistration)
.providerConfigurationMetadata(configurationMetadata)
.build();
return updatedRegistration;
Thank you.
Comment From: downvoteit
Here is a full solution based on Keycloak OpenID for the wanderers.
package com.tb.ws.cscommon.config;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientProperties;
import org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2ClientPropertiesRegistrationAdapter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Configuration
public class ClientRegistrationConfig {
@Bean
@ConditionalOnMissingBean({ClientRegistrationRepository.class})
InMemoryClientRegistrationRepository clientRegistrationRepository(
OAuth2ClientProperties properties) {
List<ClientRegistration> registrations =
OAuth2ClientPropertiesRegistrationAdapter.getClientRegistrations(properties)
.values()
.stream()
.map(
o ->
ClientRegistration.withClientRegistration(o)
.providerConfigurationMetadata(
Map.of(
"end_session_endpoint",
"http://127.0.0.1:8080/auth/realms/OAuth2/protocol/openid-connect/logout"))
.build())
.collect(Collectors.toList());
return new InMemoryClientRegistrationRepository(registrations);
}
}
We alter properties loading bean required for immutable InMemoryClientRegistrationRepository initialization.
Comment From: uavst
@pthorson could you please provide the complete class for this customisation?
OK I was still on 5.2.0 M2. I see the new method now that I have upgraded 5.2.1.
The ClientRegistration Build still sets the Map unmodifiable in its call to create:
providerDetails.configurationMetadata = Collections.unmodifiableMap(this.configurationMetadata);So I just have to copy it after grabbing it and then it can be modified and built again:
Map<String, Object> unmofifiableConfigurationMetadata = clientRegistration.getProviderDetails().getConfigurationMetadata(); Map<String, Object> configurationMetadata = new HashMap<>(unmofifiableConfigurationMetadata); configurationMetadata.put("end_session_endpoint", "my_uri"); ClientRegistration updatedRegistration = ClientRegistration.withClientRegistration(clientRegistration) .providerConfigurationMetadata(configurationMetadata) .build(); return updatedRegistration;Thank you.