@@ -3,11 +3,15 @@ package providers
33import (
44 "context"
55 "fmt"
6+ "net/http"
67 "time"
78
89 oidc "github.com/coreos/go-oidc"
910 "github.com/pusher/oauth2_proxy/pkg/apis/sessions"
11+ "github.com/pusher/oauth2_proxy/pkg/requests"
12+
1013 "golang.org/x/oauth2"
14+
1115)
1216
1317// OIDCProvider represents an OIDC based Identity Provider
@@ -117,8 +121,31 @@ func (p *OIDCProvider) createSessionState(ctx context.Context, token *oauth2.Tok
117121 }
118122
119123 if claims.Email == "" {
120− // TODO: Try getting email from /userinfo before falling back to Subject
121− claims.Email = claims.Subject
124+ if p.ProfileURL.String() == "" {
125+ return nil, fmt.Errorf("id_token did not contain an email")
126+ }
127+
128+ // If the userinfo endpoint profileURL is defined, then there is a chance the userinfo
129+ // contents at the profileURL contains the email.
130+ // Make a query to the userinfo endpoint, and attempt to locate the email from there.
131+
132+ req, err := http.NewRequest("GET", p.ProfileURL.String(), nil)
133+ if err != nil {
134+ return nil, err
135+ }
136+ req.Header = getOIDCHeader(token.AccessToken)
137+
138+ json, err := requests.Request(req)
139+ if err != nil {
140+ return nil, err
141+ }
142+
143+ email, err := json.Get("email").String()
144+ if err != nil {
145+ return nil, fmt.Errorf("id_token nor userinfo endpoint did not contain an email")
146+ }
147+
148+ claims.Email = email
122149 }
123150 if !p.AllowUnverifiedEmail && claims.Verified != nil && !*claims.Verified {
124151 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 {
145172
146173 return true
147174}
175+
176+func getOIDCHeader(access_token string) http.Header {
177+ header := make(http.Header)
178+ header.Set("Accept", "application/json")
179+ header.Set("Authorization", fmt.Sprintf("Bearer %s", access_token))
180+ return header
181+}