-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Conversation
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 |
There was a problem hiding this 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
} | ||
|
||
c.Secret = "" | ||
if c.Metadata != nil { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 :)
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
@aeneasr I added the adjustments required. Please have a look when you can ;) |
There was a problem hiding this 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...
client/handler.go
Outdated
h.r.Writer().WriteError(w, r, err) | ||
return | ||
} | ||
token, _, err := h.r.OpenIDJWTStrategy().Generate(r.Context(), jwtgo.MapClaims{ |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
@aeneasr I did mentioned changes :) Please review when you have some time |
There was a problem hiding this 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 :(
client/handler.go
Outdated
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] |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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?
@aeneasr I update the PR based on your comments... Could you please have a look when you have some time? :) |
Could you please enable write access for maintainers? 🤔 Thank you! 🙏 |
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?
|
Codecov Report
@@ 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
Continue to review full report at Codecov.
|
@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? |
@aeneasr Can you please review when you have some time? |
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! |
It looks like my changes to the PR got lost. Have you tried enabling write access for me? I will have to redo all the changes again but first we need to ensure that this is working. :/ |
Looks like I still don't have write rights :/ I will have to figure out another way to complete and review this PR. |
Hi @aeneasr I checked you have access to this repo... So I am wandering what the problem is.. BTW I merged from hydra repo into for fork repository |
Somehow this PR got stuck. Is there anything where I could help to finish this? |
See: #2909 |
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
@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 |
…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>
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 whenallow_dynamic_registration
configuration is set to true.Checklist
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.
works.
Further comments
Please let me know if something else needs to be done in order to build successfully without changes mentioned above.