git.iko.soy/typeable/oauth2-proxy
on master help sign in
Merge pull request #146 from pusher/no-infer-username

Do not infer username from email

commit908ac24257840b197163c6e0bec8954b56ca3656 authorPhil Taprogge <philt@pusher.com> dateThu 9 May 2019, 10:30 (7 years ago) parentec036d1d4341ec
7 files changed+41−27
CHANGELOG.md+9 Makefile+1−1 oauthproxy_test.go+6−5 providers/google.go+19−16 providers/oidc.go+1 providers/session_state.go+1−1 providers/session_state_test.go+4−4
CHANGELOG.md+9
@@ -1,7 +1,16 @@
11# Vx.x.x (Pre-release)
22
3+## Breaking Changes
4+
5+- [#146](https://github.com/pusher/oauth2_proxy/pull/146) Use full email address as `User` if the auth response did not contain a `User` field (@gargath)
6+ - This change modifies the contents of the `X-Forwarded-User` header supplied by the proxy for users where the auth response from the IdP did not contain
7+ a username.
8+ In that case, this header used to only contain the local part of the user's email address (e.g. `john.doe` for `john.doe@example.com`) but now contains
9+ the user's full email address instead.
10+
311## Changes since v3.2.0
412
13+- [#146](https://github.com/pusher/oauth2_proxy/pull/146) Use full email address as `User` if the auth response did not contain a `User` field (@gargath)
514- [#144](https://github.com/pusher/oauth2_proxy/pull/144) Use GO 1.12 for ARM builds (@kskewes)
615- [#142](https://github.com/pusher/oauth2_proxy/pull/142) ARM Docker USER fix (@kskewes)
716- [#52](https://github.com/pusher/oauth2_proxy/pull/52) Logging Improvements (@MisterWil)
Makefile+1−1
@@ -75,7 +75,7 @@ docker-push-all: docker-push
7575
7676.PHONY: test
7777test: dep lint
78− $(GO) test -v -race $(go list ./... | grep -v /vendor/)
78+ $(GO) test -v -race ./...
7979
8080.PHONY: release
8181release: lint test
oauthproxy_test.go+6−5
@@ -291,8 +291,7 @@ func TestBasicAuthPassword(t *testing.T) {
291291 opts.Validate()
292292
293293 providerURL, _ := url.Parse(providerServer.URL)
294− const emailAddress = "michael.bland@gsa.gov"
295− const username = "michael.bland"
294+ const emailAddress = "john.doe@example.com"
296295
297296 opts.provider = NewTestProvider(providerURL, emailAddress)
298297 proxy := NewOAuthProxy(opts, func(email string) bool {
@@ -335,7 +334,9 @@ func TestBasicAuthPassword(t *testing.T) {
335334 rw = httptest.NewRecorder()
336335 proxy.ServeHTTP(rw, req)
337336
338− expectedHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(username+":"+opts.BasicAuthPassword))
337+ // The username in the basic auth credentials is expected to be equal to the email address from the
338+ // auth response, so we use the same variable here.
339+ expectedHeader := "Basic " + base64.StdEncoding.EncodeToString([]byte(emailAddress+":"+opts.BasicAuthPassword))
339340 assert.Equal(t, expectedHeader, rw.Body.String())
340341 providerServer.Close()
341342}
@@ -654,13 +655,13 @@ func (p *ProcessCookieTest) LoadCookiedSession() (*providers.SessionState, time.
654655func TestLoadCookiedSession(t *testing.T) {
655656 pcTest := NewProcessCookieTestWithDefaults()
656657
657− startSession := &providers.SessionState{Email: "michael.bland@gsa.gov", AccessToken: "my_access_token"}
658+ startSession := &providers.SessionState{Email: "john.doe@example.com", AccessToken: "my_access_token"}
658659 pcTest.SaveSession(startSession, time.Now())
659660
660661 session, _, err := pcTest.LoadCookiedSession()
661662 assert.Equal(t, nil, err)
662663 assert.Equal(t, startSession.Email, session.Email)
663− assert.Equal(t, "michael.bland", session.User)
664+ assert.Equal(t, "john.doe@example.com", session.User)
664665 assert.Equal(t, startSession.AccessToken, session.AccessToken)
665666}
666667
providers/google.go+19−16
@@ -29,6 +29,12 @@ type GoogleProvider struct {
2929 GroupValidator func(string) bool
3030}
3131
32+type claims struct {
33+ Subject string `json:"sub"`
34+ Email string `json:"email"`
35+ EmailVerified bool `json:"email_verified"`
36+}
37+
3238// NewGoogleProvider initiates a new GoogleProvider
3339func NewGoogleProvider(p *ProviderData) *GoogleProvider {
3440 p.ProviderName = "Google"
@@ -64,7 +70,7 @@ func NewGoogleProvider(p *ProviderData) *GoogleProvider {
6470 }
6571}
6672
67−func emailFromIDToken(idToken string) (string, error) {
73+func claimsFromIDToken(idToken string) (*claims, error) {
6874
6975 // id_token is a base64 encode ID token payload
7076 // https://developers.google.com/accounts/docs/OAuth2Login#obtainuserinfo
@@ -72,24 +78,21 @@ func emailFromIDToken(idToken string) (string, error) {
7278 jwtData := strings.TrimSuffix(jwt[1], "=")
7379 b, err := base64.RawURLEncoding.DecodeString(jwtData)
7480 if err != nil {
75− return "", err
81+ return nil, err
7682 }
7783
78− var email struct {
79− Email string `json:"email"`
80− EmailVerified bool `json:"email_verified"`
81− }
82− err = json.Unmarshal(b, &email)
84+ c := &claims{}
85+ err = json.Unmarshal(b, c)
8386 if err != nil {
84− return "", err
87+ return nil, err
8588 }
86− if email.Email == "" {
87− return "", errors.New("missing email")
89+ if c.Email == "" {
90+ return nil, errors.New("missing email")
8891 }
89− if !email.EmailVerified {
90− return "", fmt.Errorf("email %s not listed as verified", email.Email)
92+ if !c.EmailVerified {
93+ return nil, fmt.Errorf("email %s not listed as verified", c.Email)
9194 }
92− return email.Email, nil
95+ return c, nil
9396}
9497
9598// Redeem exchanges the OAuth2 authentication token for an ID token
@@ -138,8 +141,7 @@ func (p *GoogleProvider) Redeem(redirectURL, code string) (s *SessionState, err
138141 if err != nil {
139142 return
140143 }
141− var email string
142− email, err = emailFromIDToken(jsonResponse.IDToken)
144+ c, err := claimsFromIDToken(jsonResponse.IDToken)
143145 if err != nil {
144146 return
145147 }
@@ -148,7 +150,8 @@ func (p *GoogleProvider) Redeem(redirectURL, code string) (s *SessionState, err
148150 IDToken: jsonResponse.IDToken,
149151 ExpiresOn: time.Now().Add(time.Duration(jsonResponse.ExpiresIn) * time.Second).Truncate(time.Second),
150152 RefreshToken: jsonResponse.RefreshToken,
151− Email: email,
153+ Email: c.Email,
154+ User: c.Subject,
152155 }
153156 return
154157}
providers/oidc.go+1
@@ -128,6 +128,7 @@ func (p *OIDCProvider) createSessionState(ctx context.Context, token *oauth2.Tok
128128 RefreshToken: token.RefreshToken,
129129 ExpiresOn: token.Expiry,
130130 Email: claims.Email,
131+ User: claims.Subject,
131132 }, nil
132133}
133134
providers/session_state.go+1−1
@@ -218,7 +218,7 @@ func DecodeSessionState(v string, c *cookie.Cipher) (*SessionState, error) {
218218 }
219219 }
220220 if ss.User == "" {
221− ss.User = strings.Split(ss.Email, "@")[0]
221+ ss.User = ss.Email
222222 }
223223 return ss, nil
224224}
providers/session_state_test.go+4−4
@@ -30,7 +30,7 @@ func TestSessionStateSerialization(t *testing.T) {
3030 ss, err := DecodeSessionState(encoded, c)
3131 t.Logf("%#v", ss)
3232 assert.Equal(t, nil, err)
33− assert.Equal(t, "user", ss.User)
33+ assert.Equal(t, "user@domain.com", ss.User)
3434 assert.Equal(t, s.Email, ss.Email)
3535 assert.Equal(t, s.AccessToken, ss.AccessToken)
3636 assert.Equal(t, s.IDToken, ss.IDToken)
@@ -41,7 +41,7 @@ func TestSessionStateSerialization(t *testing.T) {
4141 ss, err = DecodeSessionState(encoded, c2)
4242 t.Logf("%#v", ss)
4343 assert.Equal(t, nil, err)
44− assert.NotEqual(t, "user", ss.User)
44+ assert.NotEqual(t, "user@domain.com", ss.User)
4545 assert.NotEqual(t, s.Email, ss.Email)
4646 assert.Equal(t, s.ExpiresOn.Unix(), ss.ExpiresOn.Unix())
4747 assert.NotEqual(t, s.AccessToken, ss.AccessToken)
@@ -97,7 +97,7 @@ func TestSessionStateSerializationNoCipher(t *testing.T) {
9797 // only email should have been serialized
9898 ss, err := DecodeSessionState(encoded, nil)
9999 assert.Equal(t, nil, err)
100− assert.Equal(t, "user", ss.User)
100+ assert.Equal(t, "user@domain.com", ss.User)
101101 assert.Equal(t, s.Email, ss.Email)
102102 assert.Equal(t, "", ss.AccessToken)
103103 assert.Equal(t, "", ss.RefreshToken)
@@ -203,7 +203,7 @@ func TestDecodeSessionState(t *testing.T) {
203203 {
204204 SessionState: SessionState{
205205 Email: "user@domain.com",
206− User: "user",
206+ User: "user@domain.com",
207207 },
208208 Encoded: `{"Email":"user@domain.com"}`,
209209 },