Skip to content
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

feat: Public api for OIDC dynamic client registration #2568

Closed
wants to merge 29 commits into from

Conversation

fjvierap
Copy link
Contributor

@fjvierap fjvierap commented Jun 15, 2021

Related issue

#2549

Proposed changes

Create a separate endpoint for create, get, update and delete clients form public api. The new endpoint will only be available when SERVE_PUBLIC_ALLOW_DYNAMIC_REGISTRATION is set to true or when allow_dynamic_registration configuration is set to true.

Checklist

  • [ x] I have read the contributing guidelines.
  • [ x] I have read the security policy.
  • [ x] I confirm that this pull request does not address a security
    vulnerability. If this pull request addresses a security. vulnerability, I
    confirm that I got green light (please contact
    security@ory.sh) from the maintainers to push
    the changes.
  • [x ] I have added tests that prove my fix is effective or that my feature
    works.
  • [x ] I have added or changed the documentation.

Further comments

Please let me know if something else needs to be done in order to build successfully without changes mentioned above.

@fjvierap fjvierap changed the title Public api for dynamic client registration feat: Public api for dynamic client registration Jun 15, 2021
@fjvierap fjvierap changed the title feat: Public api for dynamic client registration feat: Public api for OIDC dynamic client registration Jun 15, 2021
@aeneasr
Copy link
Member

aeneasr commented Jun 17, 2021

Ready for 👀 ? :) If so you can always request a review from me so it shows up on my radar :)

@fjvierap
Copy link
Contributor Author

Ready for 👀 ? :) If so you can always request a review from me so it shows up on my radar :)

Yes it is ready for review ;-)... Please check when you have some time

Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! This is a great starting point! I have some ideas how to improve the PR.

One thing noteworthy is the question if we want to implement OpenID Connect Dynamic Client Registration OR OAuth2 Dynamic Registration or both. Depending on that, the authentication mechanisms and payloads might change.

I think it makes more sense for us to implement the OIDC spec because that's what we've implemented already, plus we can easily certify it.

client/handler.go Outdated Show resolved Hide resolved
client/handler.go Outdated Show resolved Hide resolved
client/handler.go Outdated Show resolved Hide resolved
client/handler.go Outdated Show resolved Hide resolved
client/validator.go Show resolved Hide resolved
client/validator.go Outdated Show resolved Hide resolved
client/handler.go Outdated Show resolved Hide resolved
client/handler.go Outdated Show resolved Hide resolved
client/handler.go Outdated Show resolved Hide resolved
client/handler.go Outdated Show resolved Hide resolved
}

c.Secret = ""
if c.Metadata != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Metadata has a different meaning. It's purpose is not to store configuration for the client, but to store any arbitrary data. Adding access_token_ttl here is not metadata, imo, but configuration. Therefore I think that it would be better to have, for example, on the admin port:

POST /clients/<id>/settings

which would allow to change the config of clients - so for example the access token TTL.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Repurposing this field for some other functionality makes Ory Hydra vulnerable. Say you have Hydra 1.10 running. Someone scans you and sees that you use Ory Hydra 1.10 and have this endpoint exposed. He/she adds config options to the client in the metadata field. One day, you upgrade to Ory Hydra 1.11. Now, the attacker was able to change configuration which he was not supposed to change.

Therefore, this has to go somewhere else! It's generally a good idea to never use untrusted data as trusted data. Validation might help but it often fails to cover all areas :)

Copy link
Contributor Author

@fjvierap fjvierap Jun 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand..... How about have and access_token_ttl or access_token_ttl as specific fields in the root level? As now we will different endpoints for Dynamic Client registration and the /client ones in the admin API. Then we can have different client representations and we can include those access_token_ttl or access_token_ttl only in the one for admin API... Then hydra master can keep that configuration in sync... Does it make sense?

Separate the client representation for Dynamic Client registration and the admin api maybe can be done in separate PR?

Copy link
Contributor

@dadrus dadrus Jun 22, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Javier, I'm somehow lost by your question:

Separate the client representation for Dynamic Client registration and the admin api maybe can be done in separate PR?

The purpose of #2549 was exactly to achieve this - have two independent APIs (for dynamic client registration according to OIDC spec and for client management). And this also means specific client data representations.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dadrus I mean to have access_token_ttl or access_token_ttl as dedicated fields fields for the client entity and not as part of metadata...

For this PR we will separate the public and admin endpoints... making public ones for Dynamic Client Registration to do no accept any metadata.

Does it make sense?

@fjvierap
Copy link
Contributor Author

@aeneasr I added the adjustments required. Please have a look when you can ;)

Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! A few more things but this is definitely going in the right direction :)

Sorry for being so slow with reviews these past days...

internal/config/config.yaml Outdated Show resolved Hide resolved
h.r.Writer().WriteError(w, r, err)
return
}
token, _, err := h.r.OpenIDJWTStrategy().Generate(r.Context(), jwtgo.MapClaims{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the idea is good :) Unfortunately I would say that we shouldn't use an ID Token as proof of authorization for the client. I think the basic auth model you have used is enough security. The problem here is that this token could be used as an ID token for the application which would be quite confusing to the apps.

Additionally, it would only be valid for an hour and I don't see a way of getting a new token for this?

So I think relying on basic auth is enough! It would also de-complicate the codebase.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aeneasr I did mentioned changes :) Please review when you have some time

@fjvierap
Copy link
Contributor Author

Thank you! A few more things but this is definitely going in the right direction :)

Sorry for being so slow with reviews these past days...

@aeneasr I did mentioned changes :) Please review when you have some time

Copy link
Member

@aeneasr aeneasr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh man, I had this review started but apparently never clicked on submit. Sorry :(

Comment on lines 526 to 558
func (h *Handler) validateDynClientRegistrationAuthorization(r *http.Request, c Client) error {

basicAuth := getBasicAuth(r)
if basicAuth == "" {
return herodot.ErrUnauthorized.WithReason("Invalid authorization")
}
sDec, err := base64.StdEncoding.DecodeString(basicAuth)
if err != nil {
return herodot.ErrUnauthorized.WithReason("Invalid authorization")
}
split := strings.SplitN(string(sDec), ":", 2)
if len(split) != 2 {
return herodot.ErrUnauthorized.WithReason("Invalid authorization")
}
if c.OutfacingID != split[0] {
return herodot.ErrUnauthorized.WithReason("Invalid authorization")
}
_, err = h.r.ClientManager().Authenticate(r.Context(), split[0], []byte(split[1]))
if err != nil {
return herodot.ErrUnauthorized.WithReason("Invalid authorization")
}
return nil
}

func getBasicAuth(req *http.Request) string {
auth := req.Header.Get("Authorization")
split := strings.SplitN(auth, " ", 2)
if len(split) != 2 || !strings.EqualFold(split[0], "Basic") {
// Nothing in Authorization header
return ""
}

return split[1]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add unit tests for this? Specifically for the decoding part :) Also, I think it makes sense to reuse the authentication from here: https://github.com/ory/fosite/blob/a4ce3544c2996a99b65350d4b200967df9fc0d45/client_authentication.go#L311

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@aeneasr I create a unit test for this... I think https://github.com/ory/fosite/blob/a4ce3544c2996a99b65350d4b200967df9fc0d45/client_authentication.go#L311 is for getting client credentials form request body we have basic authentication, we have in Authorization header. right?

quickstart-postgres.yml Outdated Show resolved Hide resolved
cypress/integration/openid/dynamic_client_registration.js Outdated Show resolved Hide resolved
cypress/integration/openid/dynamic_client_registration.js Outdated Show resolved Hide resolved
@fjvierap
Copy link
Contributor Author

@aeneasr I update the PR based on your comments... Could you please have a look when you have some time? :)

@aeneasr
Copy link
Member

aeneasr commented Jul 14, 2021

Could you please enable write access for maintainers? 🤔

Thank you! 🙏

@aeneasr
Copy link
Member

aeneasr commented Jul 14, 2021

I think one problem also is that this PR is against your fork's master branch, maybe that's why I get push denied. Do you have some branch protection enabled in your fork?


To github.com:fjvierap/hydra.git
 ! [remote rejected]     fjvierap/master -> fjvierap/master (permission denied)
error: Fehler beim Versenden einiger Referenzen nach 'github.com:fjvierap/hydra.git'

@codecov
Copy link

codecov bot commented Jul 14, 2021

Codecov Report

Merging #2568 (7d770e0) into master (beb72e4) will decrease coverage by 3.73%.
The diff coverage is 10.29%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2568      +/-   ##
==========================================
- Coverage   52.89%   49.15%   -3.74%     
==========================================
  Files         235      244       +9     
  Lines       14132    15295    +1163     
==========================================
+ Hits         7475     7519      +44     
- Misses       6027     7119    +1092     
- Partials      630      657      +27     
Impacted Files Coverage Δ
.../client/admin/accept_consent_request_parameters.go 35.71% <0.00%> (-1.79%) ⬇️
...t/client/admin/accept_consent_request_responses.go 19.23% <0.00%> (ø)
...nt/client/admin/accept_login_request_parameters.go 35.71% <0.00%> (-1.79%) ⬇️
...ent/client/admin/accept_login_request_responses.go 23.80% <0.00%> (ø)
...t/client/admin/accept_logout_request_parameters.go 29.16% <0.00%> (-2.09%) ⬇️
...nt/client/admin/accept_logout_request_responses.go 19.23% <0.00%> (ø)
...client/admin/create_json_web_key_set_parameters.go 32.07% <0.00%> (-1.89%) ⬇️
.../client/admin/create_json_web_key_set_responses.go 14.70% <0.00%> (ø)
...t/client/admin/create_o_auth2_client_parameters.go 26.08% <0.00%> (-2.18%) ⬇️
...nt/client/admin/create_o_auth2_client_responses.go 14.70% <0.00%> (ø)
... and 138 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update beb72e4...7d770e0. Read the comment docs.

@fjvierap
Copy link
Contributor Author

fjvierap commented Jul 19, 2021

@aeneasr I did the mentioned changed and merger ory/hydra master into my repo... But It fails because a vulnerability issue It also fails in my local in ory hydra repository but it worked in the pipeline

I think this issue has been fixed in https://github.com/gobuffalo/packr v1.30.1 I will create and additional PR in https://github.com/ory/x to upgrade to v1.30.1 and then adjust this one.

Anyways it would be good to know why with the same dependency check passed in master pipeline. Maybe something cached?

@fjvierap
Copy link
Contributor Author

@aeneasr Can you please review when you have some time?

@aeneasr
Copy link
Member

aeneasr commented Jul 23, 2021

Hello! Sorry again for the long review time - I did not have any time to look into open source the past 10 days. I will be able to review this next week. My goal is to merge it by then!

@aeneasr
Copy link
Member

aeneasr commented Jul 30, 2021

It looks like my changes to the PR got lost. Have you tried enabling write access for me?

#2568 (comment)

I will have to redo all the changes again but first we need to ensure that this is working. :/

@aeneasr
Copy link
Member

aeneasr commented Jul 30, 2021

Looks like I still don't have write rights :/ I will have to figure out another way to complete and review this PR.

@aeneasr
Copy link
Member

aeneasr commented Sep 20, 2021

@dadrus @fjvierap how can we proceed with this? Unfortunately, I am still lacking the rights to push to the repository which would greatly help in merging this PR.

@fjvierap
Copy link
Contributor Author

fjvierap commented Sep 23, 2021

@dadrus @fjvierap how can we proceed with this? Unfortunately, I am still lacking the rights to push to the repository which would greatly help in merging this PR.

Hi @aeneasr I checked you have access to this repo... So I am wandering what the problem is..

Screen Shot 2021-09-23 at 13 20 13

Screen Shot 2021-09-23 at 13 19 20

BTW I merged from hydra repo into for fork repository

@raman-nbg
Copy link
Contributor

Somehow this PR got stuck. Is there anything where I could help to finish this?

@aeneasr
Copy link
Member

aeneasr commented Dec 29, 2021

See: #2909

@StarAurryon StarAurryon mentioned this pull request Dec 30, 2021
7 tasks
aeneasr added a commit to fjvierap/hydra that referenced this pull request Jan 2, 2022
This feature adds first-class support for OpenID Connect Dynamic Client Registration. To enable this feature, which is disabled by default, set

```yaml
oidc:
  dynamic_client_registration:
    enabled: true
```

in your Ory Hydra configuration. Once enabled, endpoints `POST`, `GET`, `PUT`, and `DELETE` for `/openid/register` will be available at the public port!

Closes ory#2568
Closes ory#2549
@aeneasr
Copy link
Member

aeneasr commented Jan 3, 2022

@fjvierap thank you for your hard work on this PR!

I am continuing the work in #2909 . I think it makes sense to follow OAuth2 Dynamic Client Registration Protocol as well as OpenID Connect Dynamic Client Registration as closely as possible and add a large set of tests to ensure everything works as needed. This means that there still needs to be quite a lot of work done, so it will take more time for this to get merged.

I will be closing this PR and you can follow the work in #2909

@aeneasr aeneasr closed this Jan 3, 2022
aeneasr added a commit that referenced this pull request Jan 4, 2022
…lient Registration Protocol (#2909)

This feature adds first-class support for two IETF RFCs and one OpenID Spec:

- [OpenID Connect Dynamic Client Registration 1.0](https://openid.net/specs/openid-connect-registration-1_0.html)
- [OAuth 2.0 Dynamic Client Registration Protocol](https://tools.ietf.org/html/rfc7591)
- [OAuth 2.0 Dynamic Client Registration Management Protocol](https://tools.ietf.org/html/rfc7592)

To enable this feature, which is disabled by default, set

```yaml
oidc:
  dynamic_client_registration:
    enabled: true
```

in your Ory Hydra configuration. Once enabled, endpoints `POST`, `GET`, `PUT`, and `DELETE` for `/connect/register` will be available at the public port!

Closes #2568
Closes #2549

BREAKING CHANGES: Endpoint `PUT /clients` now returns a 404 error when the OAuth2 Client to be updated does not exist. It returned 401 previously. This change requires you to run SQL migrations!

Co-authored-by: fjviera <javier.viera@mindcurv.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants