-
Notifications
You must be signed in to change notification settings - Fork 1.7k
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
Add userinfo_endpoint #1454
Add userinfo_endpoint #1454
Conversation
@srenatus would be great if you could take a look at this (build checks out)! |
I'll try to get this in this week 🤞 |
Sorry about that. This week it is, then. 😅 |
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.
This is looking good so far -- thank you!
Besides my inline commits, a few points of note:
- Would you mind throwing in a test or three for the new HTTP handler, please?
- @jackielii: Are you OK with @mdbraber adopting your PR? @mdbraber could you add a
Co-authored-by
line with @jackielii on the relevant commits, please? (Or massage the history to include the commit of A simple implementation of userinfo endpoint #1201?) - Oh this has quite some history.... @fjbsantiago had a proposal up, too, in Added User Info endpoint #1133. I suppose we'll better put a bunch of hat-tips into the merge commit 🤔
Thanks again! 😃
@@ -265,6 +265,11 @@ type federatedIDClaims struct { | |||
UserID string `json:"user_id,omitempty"` | |||
} | |||
|
|||
func (s *Server) newAccessToken(clientID string, claims storage.Claims, scopes []string, nonce, connID string) (accessToken string, err error) { | |||
idToken, _, err := s.newIDToken(clientID, claims, scopes, nonce, storage.NewID(), connID) |
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.
Hmm! So we'll be using a JWT for access_token
... but it's a different one; we don't hand out the same we give as id_token
. 💭
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.
Maybe @jackielii can answer this one?
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.
Like in my original PR comment: "this is a stop gap solution". In my understanding, access_token is a "key" that should be saved away and later used to retrieve "user_info". Here I'm abusing the ID token signature verification: Use an ID token as the access token, and use signature verification to verify the JWT and just return the claims as the user_info response.
Because the access_token is opaque to the user, so this change is forward compatible with the "proper solution". I even created this function to later swap out for the proper "save to db" solution.
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.
@srenatus sorry forgot to answer your original question. Within one auth request, the id_token won't be exactly the same as the access_token, albeit access_token looks and "can" behave like a jwt id_token. We're just abusing the fact that access_token is just a "random string".
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.
Quite clever! And thanks for considering "forward compat with a proper solution" 😄
server/handlers.go
Outdated
return nil, fmt.Errorf("unable to parse signed message") | ||
} | ||
|
||
// Parse the message to check expiry, as it jose doesn't distinguish expiry error from others |
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 don't understand how the comment relates to the code below. 🤔
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.
This might be me - doing some too agressive butchering of the code. Sorry.
server/handlers.go
Outdated
// Parse the message to check expiry, as it jose doesn't distinguish expiry error from others | ||
parts := strings.Split(token, ".") | ||
if len(parts) != 3 { | ||
return nil, fmt.Errorf("square/go-jose: compact JWS format must have three parts") |
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.
Also, we should probably not claim we're square/go-jose
. We aren't 😄
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.
Well that seems an easy one to fix
Thanks for taking the time to review!
I'm not proficient in writing any sort of tests so that'll take me a lot of figuring out, I'm happy to try if someone might have some pointers how to do this.
Well I think @jackielii did most of the work as it's their patch. I only butchered the patch to make it fit the current code base :-) Happy to add a Co-authored line on the relevant commit. Massaging the history seems more work so I'll just do the first.
So it seems, so more hat tips for everyone :-) 🎩 |
@mdbraber & @srenatus absolutely. Feel free to use my name or otherwise, no probs for me. I was lazy and looking for a solution hastily, and just figured this trick should be the easiest one without changing too much. It utilises existing id_token signature verification mechanism to implement the access_token + user_info verification. It has been in semi-production in our internal system for since I submitted the other PR over a year ago. BTW, I realised on that my PR wasn't similar to the original #1133 . That one I still couldn't fully understand, and mine definitely took a different approach. But it helped to understand the code base a bit better. Thanks & Regards, |
return nil, err | ||
} | ||
|
||
// TODO: check other claims |
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.
This could be a "big" TODO. I realised later on that the jose or any other JWT token lib should do all the checks, but I'm not sure they do all the needed. Or maybe they do, and I'm just being over paranoid here to check again. Need a JWT expert or jose expert here to answer the question.
Co-authored-by: Yuxing Li <[email protected]> Co-authored-by: Francisco Santiago <[email protected]>
e6f4c27
to
3dd1bac
Compare
Added the right attribution: added Co-authored-by to @jackielii and @fjbsantiago acknowledging their work. |
https://github.com/dexidp/dex/blob/master/server/server_test.go has some tests that could be added to or expanded, I suppose. LMK if you need help. 😃 |
How's this coming along? Is there anything I can do to help? I'd like to see this land in Dex so I can better integrate it with services like AWS ALBs that require userinfo endpoints. |
@alindeman This needs tests. If you'd like to contribute, you could PR against |
Sounds good. I will plan to tackle adding some tests tomorrow. |
Supersedes #1453