Skip to content

Commit

Permalink
WIP: drafting more
Browse files Browse the repository at this point in the history
  • Loading branch information
ddubson committed Sep 28, 2023
1 parent 2875d4b commit 605cccb
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ With an access token obtained from the previous step, a client can now be dynami
The "initial" access token can only be used once.
After the client is registered, the access token is invalidated.

[[sample.ClientRegistrar]]
[[sample.basic.ClientRegistrar]]
[source,java]
----
include::{examples-dir}/main/java/sample/registration/basic/ClientRegistrar.java[]
Expand All @@ -95,7 +95,7 @@ include::{examples-dir}/main/java/sample/registration/basic/ClientRegistrar.java
<3> Sample https://openid.net/specs/openid-connect-registration-1_0.html#RegistrationRequest[Client Registration Request] using `WebClient`.
<4> Sample https://openid.net/specs/openid-connect-registration-1_0.html#ReadRequest[Client Read Request] using `WebClient`.

[[sample.ClientRegistrationExample]]
[[sample.basic.ClientRegistrationExample]]
[source,java]
----
include::{examples-dir}/main/java/sample/registration/basic/BasicClientRegistrationExample.java[]
Expand All @@ -115,7 +115,43 @@ The https://openid.net/specs/openid-connect-registration-1_0.html#ReadResponse[C
[[customize-metadata]]
== Customize client metadata

In order to accept custom client metadata during dynamic client registration, a few additional implementation details
In order to accept custom client metadata when registering a client, a few additional implementation details
are necessary.

[NOTE]
====
The following example depicts example custom metadata `logo_uri` (string type) and `contacts` (string array type)
====

[[sample.custom.CustomMetadataConfig]]
[source,java]
----
include::{examples-dir}/main/java/sample/registration/custommetadata/CustomMetadataConfig.java[]
----

<1> Create a `Consumer<List<AuthenticationProvider>>` implementation.
<2> Identify custom fields that should be accepted during client registration.
<3> Filter for `OidcClientRegistrationAuthenticationProvider` instance.
<4> Add a custom registered client `Converter` (implementation in #6)
<5> Add a custom client registration `Converter` (implementation in #7)
<6> Custom registered client `Converter` implementation that adds custom claims to registered client settings.
<7> Custom client registration `Converter` implementation that modifies client registration claims with custom metadata.

[[sample.custom.SecurityConfig]]
[source,java]
----
include::{examples-dir}/main/java/sample/registration/custommetadata/SecurityConfig.java[]
----

<1> Configure the `Consumer<List<AuthenticationProvider>>` implementation from above with client registration endpoint authentication providers.

[[sample.custom.ClientRegistrar]]
[source,java]
----
include::{examples-dir}/main/java/sample/registration/custommetadata/ClientRegistrar.java[]
----

<1> TODO
<2> TODO
<3> TODO
<4> TODO
Original file line number Diff line number Diff line change
Expand Up @@ -19,42 +19,18 @@

public class CustomMetadataConfig {
public static Consumer<List<AuthenticationProvider>> registeredClientConverters() {
return (authenticationProviders) -> // <1>
authenticationProviders.forEach(authenticationProvider -> {
List<String> customClientMetadata = List.of("logo_uri", "contacts"); // <2>
List<String> customClientMetadata = List.of("logo_uri", "contacts"); // <1>

return (authenticationProviders) -> // <2>
authenticationProviders.forEach(authenticationProvider -> {
if (authenticationProvider instanceof OidcClientRegistrationAuthenticationProvider provider) { // <3>
provider.setRegisteredClientConverter(new CustomRegisteredClientConverter(customClientMetadata)); // <4>
provider.setClientRegistrationConverter(new CustomClientRegistrationConverter(customClientMetadata)); // <5>
}
});
}

static class CustomClientRegistrationConverter implements Converter<RegisteredClient, OidcClientRegistration> { // <6>
private final List<String> customMetadata;

private final RegisteredClientOidcClientRegistrationConverter delegate;

CustomClientRegistrationConverter(List<String> customMetadata) {
this.customMetadata = customMetadata;
this.delegate = new RegisteredClientOidcClientRegistrationConverter();
}

public OidcClientRegistration convert(RegisteredClient registeredClient) {
var clientRegistration = delegate.convert(registeredClient);
Map<String, Object> claims = new HashMap<>(clientRegistration.getClaims());
if (!CollectionUtils.isEmpty(customMetadata)) {
ClientSettings clientSettings = registeredClient.getClientSettings();

claims.putAll(customMetadata.stream()
.filter(metadatum -> clientSettings.getSetting(metadatum) != null)
.collect(Collectors.toMap(Function.identity(), clientSettings::getSetting)));
}
return OidcClientRegistration.withClaims(claims).build();
}
}

static class CustomRegisteredClientConverter implements Converter<OidcClientRegistration, RegisteredClient> { // <7>
static class CustomRegisteredClientConverter implements Converter<OidcClientRegistration, RegisteredClient> { // <6>
private final List<String> customMetadata;

private final OidcClientRegistrationRegisteredClientConverter delegate;
Expand All @@ -80,4 +56,29 @@ public RegisteredClient convert(OidcClientRegistration clientRegistration) {
return RegisteredClient.from(convertedClient).clientSettings(clientSettingsBuilder.build()).build();
}
}

static class CustomClientRegistrationConverter implements Converter<RegisteredClient, OidcClientRegistration> { // <7>
private final List<String> customMetadata;

private final RegisteredClientOidcClientRegistrationConverter delegate;

CustomClientRegistrationConverter(List<String> customMetadata) {
this.customMetadata = customMetadata;
this.delegate = new RegisteredClientOidcClientRegistrationConverter();
}

public OidcClientRegistration convert(RegisteredClient registeredClient) {
var clientRegistration = delegate.convert(registeredClient);
Map<String, Object> claims = new HashMap<>(clientRegistration.getClaims());
if (!CollectionUtils.isEmpty(customMetadata)) {
ClientSettings clientSettings = registeredClient.getClientSettings();

claims.putAll(customMetadata.stream()
.filter(metadatum -> clientSettings.getSetting(metadatum) != null)
.collect(Collectors.toMap(Function.identity(), clientSettings::getSetting)));
}
return OidcClientRegistration.withClaims(claims).build();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

import java.util.UUID;

import static sample.registration.custommetadata.CustomMetadataConfig.*;

@Configuration
@EnableWebSecurity
public class SecurityConfig {
Expand All @@ -24,7 +26,7 @@ public SecurityFilterChain authorizationServerSecurityFilterChain(HttpSecurity h
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http);
http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
.oidc(oidc -> oidc.clientRegistrationEndpoint(endpoint -> {
endpoint.authenticationProviders(CustomMetadataConfig.registeredClientConverters()); // <1>
endpoint.authenticationProviders(registeredClientConverters()); // <1>
}));
http.oauth2ResourceServer(oauth2ResourceServer ->
oauth2ResourceServer.jwt(Customizer.withDefaults()));
Expand Down

0 comments on commit 605cccb

Please sign in to comment.