Add OIDC support for UserInfo Endpoint Email Verification
* 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 * First, attempt to retrieve email from JWT token claims. Then fall back to requesting email from userinfo endpoint. * Don't fallback to subject for email https://github.com/bitly/oauth2_proxy/pull/481
This commit is contained in:
parent
8635391543
commit
2eecf756e4
@ -3,11 +3,15 @@ package providers
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
oidc "github.com/coreos/go-oidc"
|
oidc "github.com/coreos/go-oidc"
|
||||||
"github.com/pusher/oauth2_proxy/pkg/apis/sessions"
|
"github.com/pusher/oauth2_proxy/pkg/apis/sessions"
|
||||||
|
"github.com/pusher/oauth2_proxy/pkg/requests"
|
||||||
|
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// OIDCProvider represents an OIDC based Identity Provider
|
// OIDCProvider represents an OIDC based Identity Provider
|
||||||
@ -117,8 +121,31 @@ func (p *OIDCProvider) createSessionState(ctx context.Context, token *oauth2.Tok
|
|||||||
}
|
}
|
||||||
|
|
||||||
if claims.Email == "" {
|
if claims.Email == "" {
|
||||||
// TODO: Try getting email from /userinfo before falling back to Subject
|
if p.ProfileURL.String() == "" {
|
||||||
claims.Email = claims.Subject
|
return nil, fmt.Errorf("id_token did not contain an email")
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the userinfo endpoint profileURL is defined, then there is a chance the userinfo
|
||||||
|
// contents at the profileURL contains the email.
|
||||||
|
// Make a query to the userinfo endpoint, and attempt to locate the email from there.
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", p.ProfileURL.String(), nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header = getOIDCHeader(token.AccessToken)
|
||||||
|
|
||||||
|
json, err := requests.Request(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
email, err := json.Get("email").String()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("id_token nor userinfo endpoint did not contain an email")
|
||||||
|
}
|
||||||
|
|
||||||
|
claims.Email = email
|
||||||
}
|
}
|
||||||
if !p.AllowUnverifiedEmail && claims.Verified != nil && !*claims.Verified {
|
if !p.AllowUnverifiedEmail && claims.Verified != nil && !*claims.Verified {
|
||||||
return nil, fmt.Errorf("email in id_token (%s) isn't verified", claims.Email)
|
return nil, fmt.Errorf("email in id_token (%s) isn't verified", claims.Email)
|
||||||
@ -145,3 +172,10 @@ func (p *OIDCProvider) ValidateSessionState(s *sessions.SessionState) bool {
|
|||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getOIDCHeader(access_token string) http.Header {
|
||||||
|
header := make(http.Header)
|
||||||
|
header.Set("Accept", "application/json")
|
||||||
|
header.Set("Authorization", fmt.Sprintf("Bearer %s", access_token))
|
||||||
|
return header
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user