Skip to content

Simplify dynamic client registration with custom metadata #1172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dsukhoroslov opened this issue Apr 18, 2023 · 13 comments
Closed

Simplify dynamic client registration with custom metadata #1172

dsukhoroslov opened this issue Apr 18, 2023 · 13 comments
Assignees
Labels
type: enhancement A general enhancement
Milestone

Comments

@dsukhoroslov
Copy link

Expected Behavior

  • RegisteredClient/OidcClientRegistration classes should provide access any Client Metadata parameters as per OIDC DCR spec
  • RegisteredClientRepository should be able to store and retrieve any custom Client Metadata parameters.

Current Behavior

  • Current DCR implementation supports only limited set of Client Metadata parameters

Context
in our project we need to register clients with some additional parameters which used in communication with downstream systems. It should be possible as per OIDC DCR spec, but the current implementation supports only limited set of Client Metadata parameters (even not custom, but specified in the spec). Could you consider to extend the current DCR implementation a bit? The most flexible way would be to store initial Client Registration request body as raw JSON string in DB and also provide access to it in RegistreredClient/OidcClientRegistration classes with generic Map<String, Object> interface, probably. Some CustomClientMetadataValidator component could be also useful to be able to customise Client Metadata validation.

@dsukhoroslov dsukhoroslov added the type: enhancement A general enhancement label Apr 18, 2023
@jgrandja jgrandja changed the title store and provide access to custom Client Metadata parameters Simplify dynamic client registration with custom metadata Apr 24, 2023
@jgrandja
Copy link
Collaborator

@dsukhoroslov It's already possible to store custom client metadata during dynamic client registration and access it from RegisteredClient. I've added the following test to demonstrate usage:

You will notice some code duplication in the test so we'll look at improving it. If there is anything else you would like to suggest for improvement please let us know.

@jgrandja jgrandja added this to the 1.2.x milestone Apr 24, 2023
@dsukhoroslov
Copy link
Author

dsukhoroslov commented Apr 26, 2023

@jgrandja thank you so much for the hint, using it I was able to store custom client metadata in RegisteredClient. if Converter would be public and not final then it should be possible just to extend it and not duplicate its code, probably..

@jgrandja
Copy link
Collaborator

@dsukhoroslov I'm glad it worked out 👍

I'm going to re-open this issue as we will likely make the Converter public to allow for better reuse.

@jgrandja jgrandja reopened this Apr 26, 2023
@dsukhoroslov
Copy link
Author

ah, ok 👍

@jgrandja jgrandja removed this from the 1.2.0-M1 milestone Jun 15, 2023
@ddubson
Copy link
Contributor

ddubson commented Jul 21, 2023

@jgrandja - may I request assignment on this issue?

@ddubson
Copy link
Contributor

ddubson commented Jul 23, 2023

@jgrandja - as part of my research on this enhancement, I realized I can easily address #647 as well as it is directly related. Thoughts on that?

@jgrandja
Copy link
Collaborator

@ddubson That would be great. But let's keep them separate and submit as separate PR's. Thanks.

@ddubson
Copy link
Contributor

ddubson commented Jul 26, 2023

@jgrandja -- here is the breakdown of this task as per my understanding. Please let me know if this makes sense or if you have any revisions.

Issue
when an end-user attempts to dynamically register a new client via /connect/register and they would like to include custom metadata fields along with the supported DCR fields, they are unable to do so -- the custom fields in the request body, once the client is created, are simply ignored. The response body at creation time does not contain the custom fields, and likewise for the response body of a client read operation (i.e. GET /connect/register?client_id=XYZ).

Proposed solution
The auth server should be configurable to accept custom metadata that is pre-registered ahead of time. What this means it that an auth server developer shall register specific custom metadata fields, and then, at client registration time, if that specific field is part of the request, that field shall be saved as a client registration claim and returned back to the user as part of the registration response body and as part of client read response body. Any custom metadata field that is not registered shall be ignored.

Example workflow
An end-user wants to ensure that as a client gets registered, field example_metadata shall be included as part of client registration.

  1. The authorization server must register this custom metadata field, like so:
    http.getConfigurer(OAuth2AuthorizationServerConfigurer.class)
        .oidc(oidc -> oidc.clientRegistrationEndpoint(customizer -> {
		  customizer.acceptedCustomClaims(claims -> claims.add("example_metadata"));
         }));
  1. At request POST /connect/register, the end-user may now include field example_metadata in the request body. The response body shall return this field and its value.
  2. Once registered, at request GET /connect/register?client_id=XYZ, the end user may observe field example_metadata in the response body with its proper value.

@jgrandja
Copy link
Collaborator

@ddubson I'm not sure we need to allow for pre-registered custom claims. Please take a look at this comment as well as gh-1044.

I'm thinking the solution is as follows:

  • Make OidcClientRegistrationAuthenticationProvider.OidcClientRegistrationRegisteredClientConverter public to allow for reuse and extend it to process the custom metadata in the request
  • Expose setClientRegistrationConverter(Converter<RegisteredClient, OidcClientRegistration>) as this will allow to customize the Client Registration Response to include the custom metadata
  • Make RegisteredClientOidcClientRegistrationConverter public to allow for reuse and extend it to process the custom metadata for the response

Makes sense?

@ddubson
Copy link
Contributor

ddubson commented Jul 28, 2023

Yes this makes sense to me, I understand the approach you provided -- it seems simpler to implement than what I put forward. I'll start on the implementation and will let you know if I have any follow up questions.

ddubson pushed a commit to ddubson/spring-authorization-server that referenced this issue Aug 2, 2023
ddubson pushed a commit to ddubson/spring-authorization-server that referenced this issue Aug 2, 2023
ddubson pushed a commit to ddubson/spring-authorization-server that referenced this issue Aug 16, 2023
@jgrandja jgrandja added this to the 1.2.0-M1 milestone Aug 16, 2023
ddubson added a commit to ddubson/spring-authorization-server that referenced this issue Aug 17, 2023
ddubson added a commit to ddubson/spring-authorization-server that referenced this issue Aug 19, 2023
tjholmes66 added a commit to tjholmes66/spring-authorization-server that referenced this issue Oct 2, 2023
* Update to io.spring.javaformat:spring-javaformat-checkstyle:0.0.35

Closes spring-projectsgh-1089

* Update to jackson-bom:2.14.2

Closes spring-projectsgh-1090

* Update to junit-jupiter:5.9.2

Closes spring-projectsgh-1091

* Release 1.0.1

* Next Development Version

* Update to Spring Security 6.1.0-M1

Closes spring-projectsgh-1093

* Update to nimbus-jose-jwt:9.30.2

Closes spring-projectsgh-1094

* Update to assertj-core:3.24.2

Closes spring-projectsgh-1095

* Update to mockito-core:4.11.0

Closes spring-projectsgh-1096

* Release 1.1.0-M1

* Next Development Version

* Add user property to deploy_docs workflow

* Fix broken support link

Closes spring-projectsgh-1092

* Fix client secret encoding when client dynamically registered

Closes spring-projectsgh-1056

* Polish spring-projectsgh-1056

* Allow PasswordEncoder to be configured in OidcClientRegistrationAuthenticationProvider

Issue spring-projectsgh-1056

* Upgrade client secret when available

Closes spring-projectsgh-1099

* Polish spring-projectsgh-1105

* Add support for OAuth 2.0 Device Authorization Grant

Closes spring-projectsgh-44

* Switch to spring-security SNAPSHOT dependencies

Issue spring-projectsgh-44

* Use spring-security 6.1 in snapshot tests

Issue spring-projectsgh-1106

* Update to actions/checkout@v3

Closes spring-projectsgh-1117

* Use spring-io/spring-gradle-build-action

Closes spring-projectsgh-1120

* Use spring-io/spring-gradle-build-action

Closes spring-projectsgh-1120

* Revert accidental change in versions

Issue spring-projectsgh-1120

* Polish spring-projectsgh-1106

* Update to Spring Framework 6.0.7

Closes spring-projectsgh-1130

* Update to Spring Security 1.1.0-M2

Closes spring-projectsgh-1131

* Update to nimbus-jose-jwt:9.31

Closes spring-projectsgh-1132

* Update to Spring Framework 6.0.7 in buildSrc

Issue spring-projectsgh-1130

* Release 1.1.0-M2

* Next Development Version

* Polish spring-projectsgh-1106 Device Authorization Grant

* Avoid persisting client principal in device authorization request

Issue spring-projectsgh-1106

* Polish spring-projectsgh-1068

Issue spring-projectsgh-1077

* Add OidcLogoutAuthenticationToken.isPrincipalAuthenticated()

Issue spring-projectsgh-1077

* Ensure ID Token is active before processing logout request

Issue spring-projectsgh-1077

* Allow localhost in redirect_uri

Closes spring-projectsgh-651

* Fix refresh token error code INVALID_CLIENT to INVALID_GRANT

Closes spring-projectsgh-1139

* Do not require authorizationRequest for device grant

Issue spring-projectsgh-1127

* Add tests for OAuth 2.0 Device Authorization Grant

This commit adds tests for the following components:
* AuthenticationConverters
* AuthenticationProviders
* Endpoint Filters

Issue spring-projectsgh-44
Closes spring-projectsgh-1127

* JDBC device_code authorization

Issue spring-projectsgh-1156

* Polish spring-projectsgh-1143

* Add tests and update examples in docs

Closes spring-projectsgh-1156

* Polish ref-doc

Issue spring-projectsgh-1156

* Add customization to support public clients for device grant

Issue spring-projectsgh-1157

* Polish samples

Closes spring-projectsgh-1157

* Add documentation for OAuth 2.0 Device Authorization Grant

Closes spring-projectsgh-1158

* Polish spring-projectsgh-1127

* Polish spring-projectsgh-1158

* Add documentation for OpenID Connect 1.0 Logout Endpoint

Closes spring-projectsgh-1069

* Update Stack Overflow tag to spring-authorization-server

* Update to Spring Framework 5.3.27

Closes spring-projectsgh-1162

* Update to Spring Security 5.8.3

Closes spring-projectsgh-1163

* Update to io.spring.javaformat:spring-javaformat-checkstyle:0.0.38

Closes spring-projectsgh-1164

* Update to Spring Framework 6.0.8

Closes spring-projectsgh-1165

* Update to Spring Security 6.0.3

Closes spring-projectsgh-1166

* Update to io.spring.javaformat:spring-javaformat-checkstyle:0.0.38

Closes spring-projectsgh-1167

* Update to Spring Framework 6.0.8

Closes spring-projectsgh-1168

* Update to Spring Security 6.1.0-RC1

Closes spring-projectsgh-1169

* Update to io.spring.javaformat:spring-javaformat-checkstyle:0.0.38

Closes spring-projectsgh-1170

* Update to json-path:2.8.0

Closes spring-projectsgh-1171

* Release 0.4.2

* Next Development Version

* Release 1.0.2

* Next Development Version

* Release 1.1.0-RC1

* Next Development Version

* Update to org.jfrog.buildinfo:build-info-extractor-gradle:4.29.0

Closes spring-projectsgh-1175

* Apply ArtifactoryPlugin to SpringRootProjectPlugin

Closes spring-projectsgh-1177

* Fix artifact build properties for Artifactory

- Apply SpringArtifactoryPlugin in SpringRootProjectPlugin (which applies ArtifactoryPlugin)
- In SpringArtifactoryPlugin don't set publication if MavenPublishPlugin is not applied

Closes spring-projectsgh-1179

* Add test for dynamic client registration with custom metadata

Issue spring-projectsgh-1172

* Add logout success page to default client sample

Sample client (located in 'samples/messages-client' directory) is configured with a custom logout success page where
the end-user is redirected to upon successful logout action.

Fixes spring-projectsgh-1142

* Add sample featured-authorizationserver

Issue spring-projectsgh-1189

* Merge custom-consent-authorizationserver into featured-authorizationserver

Issue spring-projectsgh-1189

* Merge federated-identity-authorizationserver into featured-authorizationserver

Issue spring-projectsgh-1189

* Update io.spring.ge.conventions plugin to 0.0.13

Closes spring-projectsgh-1190

* Update spring-asciidoctor-backends to 0.0.5

Closes spring-projectsgh-1192

* Merge device-grant-authorizationserver into featured-authorizationserver

Issue spring-projectsgh-1189

* Merge device-client into messages-client

Issue spring-projectsgh-1189

* Use custom consent page for device code flow

Issue spring-projectsgh-1189

* Use current authentication for device authorization

Issue spring-projectsgh-1189

* Reuse error handling

Issue spring-projectsgh-1189

* Handle web client response error

Issue spring-projectsgh-1189

* Update @SInCE

* Rename featured-authorizationserver to demo-authorizationserver

Issue spring-projectsgh-1189

* Rename messages-client to demo-client

Issue spring-projectsgh-1189

* Update sample README

Issue spring-projectsgh-1189

* Add integration tests for device grant

Issue spring-projectsgh-1116

* Update web ui design for demo-client

Issue spring-projectsgh-1196

* Polish web ui design for demo-client

Issue spring-projectsgh-1196

* Update web ui design for demo-authorizationserver

Issue spring-projectsgh-1196

* Polish web ui design for demo-client

Issue spring-projectsgh-1196

* Polish demo sample

Issue spring-projectsgh-1189

* Update to Spring Boot 3.1.0-RC1

Closes spring-projectsgh-1198

* Refresh Getting Started example

Closes spring-projectsgh-1186

* Use Spring Boot starter in samples

Closes spring-projectsgh-1187

* Invalidate tokens previously issued when code is reused

Closes spring-projectsgh-1152

* Polish spring-projectsgh-1152

* Add How-to: Authenticate using Social Login

Closes spring-projectsgh-538

* Add How-to: Authenticate using a Single Page Application with PKCE

Closes spring-projectsgh-539

* Hash the sid claim in the ID Token

Closes spring-projectsgh-1207

* Simplified federated login in demo sample

Closes spring-projectsgh-1208

* Polish spring-projectsgh-1186

* Polish spring-projectsgh-538

* Remove FederatedIdentityConfigurer from demo sample

Issue spring-projectsgh-1208

* Update exception handling config in ref-doc

Closes spring-projectsgh-1205

* Update exception handling config in samples

Closes spring-projectsgh-1204

* Polish ref-doc

Issue spring-projectsgh-1205

* Polish tests

* Add How-to: Implement an Extension Authorization Grant Type

Closes spring-projectsgh-686

* Update to Spring Framework 6.0.9

Closes spring-projectsgh-1213

* Update to Spring Security 6.1.0

Closes spring-projectsgh-1214

* Update to jackson-bom 2.15.0

Closes spring-projectsgh-1215

* Update to junit-jupiter 5.9.3

Closes spring-projectsgh-1216

* Release 1.1.0

* Next Development Version

* Revert serialVersionUID to 0.4.0

Closes spring-projectsgh-1218

* Revert serialVersionUID to 1.0.0

Closes spring-projectsgh-1219

* Revert serialVersionUID to 1.1.0

Closes spring-projectsgh-1220

* Exclude project dependency from spring-boot-dependencies

Closes spring-projectsgh-1228

* Update to Spring Boot 3.1.0

* Update com.gradle.enterprise plugin to 3.13.3

Closes spring-projectsgh-1234
Issue spring-projectsgh-1231

* Prepare for automated validation scripts

See https://github.com/gradle/gradle-enterprise-build-validation-scripts/blob/main/Gradle.md

Issue spring-projectsgh-1231

* ID Token contains sid claim after refresh_token grant

Closes spring-projectsgh-1224

* Use substring instead of replaceFirst in OAuth2AuthorizationConsent

Closes spring-projectsgh-1222

* Validate authorized principal instead of sub during logout

Closes spring-projectsgh-1235

* Revert "Prepare for automated validation scripts"

This reverts commit ece9f10.

Issue spring-projectsgh-1231

* Add debug log entries

Closes spring-projectsgh-1245
Closes spring-projectsgh-1246
Closes spring-projectsgh-1247
Closes spring-projectsgh-1248

* Polish additional logging

Issue spring-projectsgh-1245, spring-projectsgh-1246, spring-projectsgh-1247, spring-projectsgh-1248

* Enable caching of :asciidoctor gradle task

* Use direct code import

Issue spring-projectsgh-1231

* Next Minor Version

* Fix NPE on access token in OAuth2AuthorizationCodeAuthenticationProvider

Closes spring-projectsgh-1233

* Polish spring-projectsgh-1233

* Fix to save all values for multi-valued request parameters

Fixes spring-projectsgh-1250

* Polish spring-projectsgh-1252

* Fix to save all values for multi-valued device grant parameters

Fixes spring-projectsgh-1269

* Polish spring-projectsgh-1252

* Update to Spring Framework 5.3.28

Closes spring-projectsgh-1272

* Update to Spring Security 5.8.4

Closes spring-projectsgh-1273

* Update to jackson-bom 2.14.3

Closes spring-projectsgh-1274

* Update to Spring Framework 6.0.10

Closes spring-projectsgh-1276

* Update to Spring Security 6.0.4

Closes spring-projectsgh-1277

* Update to Spring Framework 6.0.10

Closes spring-projectsgh-1278

* Update to Spring Security 6.1.1

Closes spring-projectsgh-1279

* Update to junit-jupiter 5.9.3

Closes spring-projectsgh-1280

* Update to junit-jupiter 5.9.3

Closes spring-projectsgh-1281

* Update to jackson-bom 2.15.2

Closes spring-projectsgh-1282

* Update feature planning section to using GitHub Projects

* Release 1.1.1

* Next Development Version

* Fix generating ID token with null sid when refresh_token grant

Closes spring-projectsgh-1283

* Polish spring-projectsgh-1289

* Fix NPE in DefaultErrorController

Closes spring-projectsgh-1286

* Migrate docs to Antora

Issue spring-projectsgh-1295

* Polish Antora migration

Issue spring-projectsgh-1292
Closes spring-projectsgh-1295

* Remove unused antora-playbook.yml

* Replaces 'install' with 'publishToMavenLocal' command in README

* Adds how-to guide on adding authorities to access tokens

Closes spring-projectsgh-542

* Polish spring-projectsgh-1264

* Update order of guides in nav.adoc

* Fix userCode validation

Issue spring-projectsgh-44

* Polish spring-projectsgh-1309

* Add Revved up by Gradle Enterprise badge

* Move badges to header

This is similar to Spring Boot:
  https://github.com/spring-projects/spring-boot/blob/main/README.adoc

* Fix workflow status link

* Fix samples test suite execution and failing tests

Closes spring-projectsgh-1324

* Polish spring-projectsgh-1325

* Move deploy-docs.yml to correct folder

Issue spring-projectsgh-1295

* Remove manual list of guides

Issue spring-projectsgh-1295

* Remove reference to gh-pages

Issue spring-projectsgh-1295

* Update to Spring Framework 6.0.11

Closes spring-projectsgh-1338

* Update to Spring Security 6.1.2

Closes spring-projectsgh-1339

* Update to org.hsqldb:hsqldb 2.7.2

Closes spring-projectsgh-1340

* Release 1.1.2

* Next Development Version

* Adds ability to inject custom metadata at client registration

Closes spring-projectsgh-1172

* Polish spring-projectsgh-1326

* Adds dynamic client registration how-to guide

Closes spring-projectsgh-647

* Polish spring-projectsgh-1320

* Add code challenge methods for oidc provider configuration response

Closes spring-projectsgh-1302

* Update to Spring Framework 6.1.0-M5

Closes spring-projectsgh-1364

* Update to Spring Security 6.2.0-M3

Closes spring-projectsgh-1365

* Update to nimbus-jose-jwt 9.35

Closes spring-projectsgh-1366

* Update to junit-jupiter 5.10.0

Closes spring-projectsgh-1367

* Update to okhttp 4.11.0

Closes spring-projectsgh-1368

* Release 1.2.0-M1

* Next Development Version

---------

Co-authored-by: Joe Grandja <[email protected]>
Co-authored-by: Siva Kumar Edupuganti <[email protected]>
Co-authored-by: Yuta Saito <[email protected]>
Co-authored-by: Shannon Pamperl <[email protected]>
Co-authored-by: Steve Riesenberg <[email protected]>
Co-authored-by: HuiYeong <[email protected]>
Co-authored-by: Xu Xiaowei <[email protected]>
Co-authored-by: Janne Valkealahti <[email protected]>
Co-authored-by: Dmitriy Dubson <[email protected]>
Co-authored-by: neochae <[email protected]>
Co-authored-by: heartape <[email protected]>
Co-authored-by: Dejan Varmedja <[email protected]>
Co-authored-by: Jerome Prinet <[email protected]>
Co-authored-by: Pavel Efros <[email protected]>
Co-authored-by: Martin Lindström <[email protected]>
Co-authored-by: cbilodeau <[email protected]>
Co-authored-by: Rob Winch <[email protected]>
Co-authored-by: Dmitriy Dubson <[email protected]>
Co-authored-by: Martin Bogusz <[email protected]>
Co-authored-by: Eric Haag <[email protected]>
Co-authored-by: Tuxzx <[email protected]>
@minuth
Copy link

minuth commented Dec 8, 2024

@dsukhoroslov It's already possible to store custom client metadata during dynamic client registration and access it from RegisteredClient. I've added the following test to demonstrate usage:

You will notice some code duplication in the test so we'll look at improving it. If there is anything else you would like to suggest for improvement please let us know.

@jgrandja Would you consider adopting a design similar to Spring Security's UserDetails and UserDetailsService, where key components are based on interfaces rather than concrete classes? For instance, defining an interface for RegisteredClient could allow for greater flexibility and support for custom implementations, since the current design are hard to extend and tightly coupled to specific classes:

  1. RegisteredClient relies heavily on the builder pattern, which enforces immutability but limits extensibility for custom attributes or behaviors.
  2. RegisteredClientRepository directly depends on the RegisteredClient class, making it challenging to provide custom implementations without re-implementing or wrapping the repository.

@jgrandja
Copy link
Collaborator

@minuth

defining an interface for RegisteredClient could allow for greater flexibility and support for custom implementations, since the current design are hard to extend and tightly coupled to specific classes

Can you provide more details on the type of custom implementation you are trying to create. What new attributes are you introducing? Could you not use RegisteredClient.clientSettings for your custom attributes?

@minuth
Copy link

minuth commented Dec 12, 2024

@minuth

defining an interface for RegisteredClient could allow for greater flexibility and support for custom implementations, since the current design are hard to extend and tightly coupled to specific classes

Can you provide more details on the type of custom implementation you are trying to create. What new attributes are you introducing? Could you not use RegisteredClient.clientSettings for your custom attributes?

Of course, we can put all custom attributes in RegisteredClient.clientSettings, but it seems limited and less flexible for extending the class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: enhancement A general enhancement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants