Skip to content
This repository has been archived by the owner on Jan 24, 2019. It is now read-only.

Added OIDC support for UserInfo Endpoint Email Verification #481

Open
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

dcwangmit01
Copy link

@dcwangmit01 dcwangmit01 commented Oct 19, 2017

  • Current OIDC implementation asserts that user email check must come
    from JWT token claims. OIDC specification also allows for source
    of user email to be fetched from userinfo profile endpoint.
    http://openid.net/specs/openid-connect-core-1_0.html#UserInfo

  • Modified current code to search for email in JWT token claims
    first, and then fall back to requesting email from userinfo
    endpoint.

@dcwangmit01
Copy link
Author

dcwangmit01 commented Oct 19, 2017

Hi @jehiah @ericchiang,

I noticed that the two of you were responsible for adding the most recent OIDC provider. I was hoping for feedback on this patch which was required to make the OIDC provider work for me. I'm new to OIDC/oauth, so feedback is appreciated.

Thanks!
-dave

@dcwangmit01 dcwangmit01 force-pushed the oidc_userinfo_support branch 2 times, most recently from 5f42379 to 4f82de3 Compare October 20, 2017 00:06
Copy link
Contributor

@ericchiang ericchiang left a comment

Choose a reason for hiding this comment

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

UserInfo endpoint is optional.[1] Not all providers support it. Why not get the email from the id_token?

[1] https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata

return a.String()

// Default golang libs Encode space( ) as plus (+) instead of '%20'
// which is more proper. Some OpenID servers do not accept this
Copy link
Contributor

Choose a reason for hiding this comment

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

Which providers?

Copy link
Author

Choose a reason for hiding this comment

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

I'm integrating with the Ping Federate OIDC provider. For some reason, their API is not lenient on this. It'll totally fail with '+' as space. It's totally a purist golang library encoding thing. Check out golang/go#4013

Copy link
Author

Choose a reason for hiding this comment

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

Regarding the Email from JWT claims...

I would have preferred JWT, which would have worked with less code, but I don't have access to the Ping Federate admin panel to enable the extensions that set the openid claims in the JWT token. The documentation for the Ping Federate provider is here.

Regardless, I think the OIDC spec allows for email to be returned in either JWT claims OR the UserInfo endpoint. The code changes involving the UserInfo endpoint follow the same pattern as the LinkedIn, Gitlab, and Azure providers.

Copy link
Author

Choose a reason for hiding this comment

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

I'm going to remove the rewriting the "+" signs in the next commit. I'll put that in a separate PR as a command line option, in hopes of increasing the chances of this PR getting merged.

@dcwangmit01
Copy link
Author

Adding this comment hidden by code updates...

I think the OIDC spec allows for email to be returned in either JWT claims OR the UserInfo endpoint. The code changes involving the UserInfo endpoint follow the same pattern as the LinkedIn, Gitlab, and Azure providers. It first searches JWT token for the email. If it cannot find it in the JWT token, it falls back to searching the UserInfo endpoint.

if s.AccessToken == "" {
return "", errors.New("missing access token")
}
req, err := http.NewRequest("GET", p.ProfileURL.String(), nil)
Copy link
Contributor

Choose a reason for hiding this comment

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

How is ProfileURL set? I would have expected this to use the discovery endpoint https://accounts.google.com/.well-known/openid-configuration

Copy link
Author

Choose a reason for hiding this comment

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

Currently, the profile_url is hard-coded in each provider.

Facebook: https://github.com/bitly/oauth2_proxy/blob/master/providers/facebook.go#L32
Azure: https://github.com/bitly/oauth2_proxy/blob/master/providers/azure.go#L22
LinkedIn: https://github.com/bitly/oauth2_proxy/blob/master/providers/linkedin.go#L29

For the OIDC provider in its current state (before I submitted this PR... I left it untouched), the profile_url is untouched. In fact, it defaults to empty (""). I feed it in currently through the command line option:

  -profile-url string
        Profile access endpoint

@@ -57,10 +62,10 @@ func (p *OIDCProvider) Redeem(redirectURL, code string) (s *SessionState, err er
}

if claims.Email == "" {
return nil, fmt.Errorf("id_token did not contain an email")
log.Printf("id_token did not contain an email. Falling back on userinfo endpoint\n")
Copy link
Contributor

Choose a reason for hiding this comment

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

Perform the request to the user info endpoint here.

Copy link
Author

@dcwangmit01 dcwangmit01 Oct 20, 2017

Choose a reason for hiding this comment

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

Okay. I have no problem changing it.

I think google does it the way that you're suggeting, but they have full control over where email shows up. It will show up only in the token and no other way (as in no userinfo endpoint).

The other providers don't seem to check email in their Redeem functions. They rely on the Redeem function not returning an email, and then common oauthproxy.go:redeemCode function to notice and then hit the UserInfo endpoint.

I kind of think both places are equivalent, and I'm happy to change it if you prefer it here. Let me know your preference (after this additional information), and I can change it on Monday.

Thanks @ericchiang , for the review!

@jehiah jehiah added this to the v2.3 milestone Oct 23, 2017
dcwangmit01 and others added 4 commits January 3, 2018 10:07
* Current OIDC implementation asserts that user email check must come
  from JWT token claims.  OIDC specification also allows for source
  of user email to be fetched from userinfo profile endpoint.
  http://openid.net/specs/openid-connect-core-1_0.html#UserInfo

* Modified current code to search for email in JWT token claims
  first, and then fall back to requesting email from userinfo
  endpoint.

* Modified URL encoding to use '%20' instead of '+' for encoding
  spaces, which is more proper.  Some OpenID servers do not accept
  '+' encoding for the http query arg "scope" (e.g. bad:
  "openid+profile+email" good: "openid%20profilie%20email")
* The change was requested by @ericchiang in the pull request comments to
  PR481.
@dcwangmit01
Copy link
Author

dcwangmit01 commented Jan 6, 2018

Hi All,

I'd still like to get this pull request in. I've made the changes that @ericchiang had requested. Sorry it took a few months.

This PR has been rebased on the latest code.

-dave

@dcwangmit01
Copy link
Author

Hi @jehiah @ericchiang,

Would you mind having a look to review?

Thanks!
-dave

@dcwangmit01
Copy link
Author

@ericchiang I made the changes you've requested. Would you mind reviewing?

@Kaszaq
Copy link

Kaszaq commented Jun 11, 2018

Hello @jehiah @ericchiang,
Can this please be merged and released?

This does resolve my issue:
#615

Thanks

@dcwangmit01
Copy link
Author

Hi @jehiah @mbland @ploxiln,

Would any of you mind reviewing this pull request and potentially merging it? A few people have used this patch successfully. My teams have been using it in multiple deployments successfully for several months now. We'd love to get rid of our fork.

Thanks!

@ploxiln
Copy link
Contributor

ploxiln commented Jun 20, 2018

@mbland and I do not have permissions to merge in this repo, sorry

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Development

Successfully merging this pull request may close these issues.

None yet

5 participants