From 56da8387c0c2c432b83a82fa87d556c1e4f183dc Mon Sep 17 00:00:00 2001
From: Phil Taprogge <philt@pusher.com>
Date: Tue, 7 May 2019 11:44:19 +0100
Subject: [PATCH] Include JWT sub as User

---
 providers/google.go | 35 +++++++++++++++++++----------------
 providers/oidc.go   |  1 +
 2 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/providers/google.go b/providers/google.go
index f031bfc0..e3cb3804 100644
--- a/providers/google.go
+++ b/providers/google.go
@@ -29,6 +29,12 @@ type GoogleProvider struct {
 	GroupValidator func(string) bool
 }
 
+type claims struct {
+	Subject       string `json:"sub"`
+	Email         string `json:"email"`
+	EmailVerified bool   `json:"email_verified"`
+}
+
 // NewGoogleProvider initiates a new GoogleProvider
 func NewGoogleProvider(p *ProviderData) *GoogleProvider {
 	p.ProviderName = "Google"
@@ -64,7 +70,7 @@ func NewGoogleProvider(p *ProviderData) *GoogleProvider {
 	}
 }
 
-func emailFromIDToken(idToken string) (string, error) {
+func claimsFromIDToken(idToken string) (*claims, error) {
 
 	// id_token is a base64 encode ID token payload
 	// https://developers.google.com/accounts/docs/OAuth2Login#obtainuserinfo
@@ -72,24 +78,21 @@ func emailFromIDToken(idToken string) (string, error) {
 	jwtData := strings.TrimSuffix(jwt[1], "=")
 	b, err := base64.RawURLEncoding.DecodeString(jwtData)
 	if err != nil {
-		return "", err
+		return nil, err
 	}
 
-	var email struct {
-		Email         string `json:"email"`
-		EmailVerified bool   `json:"email_verified"`
-	}
-	err = json.Unmarshal(b, &email)
+	c := &claims{}
+	err = json.Unmarshal(b, c)
 	if err != nil {
-		return "", err
+		return nil, err
 	}
-	if email.Email == "" {
-		return "", errors.New("missing email")
+	if c.Email == "" {
+		return nil, errors.New("missing email")
 	}
-	if !email.EmailVerified {
-		return "", fmt.Errorf("email %s not listed as verified", email.Email)
+	if !c.EmailVerified {
+		return nil, fmt.Errorf("email %s not listed as verified", c.Email)
 	}
-	return email.Email, nil
+	return c, nil
 }
 
 // Redeem exchanges the OAuth2 authentication token for an ID token
@@ -138,8 +141,7 @@ func (p *GoogleProvider) Redeem(redirectURL, code string) (s *SessionState, err
 	if err != nil {
 		return
 	}
-	var email string
-	email, err = emailFromIDToken(jsonResponse.IDToken)
+	c, err := claimsFromIDToken(jsonResponse.IDToken)
 	if err != nil {
 		return
 	}
@@ -148,7 +150,8 @@ func (p *GoogleProvider) Redeem(redirectURL, code string) (s *SessionState, err
 		IDToken:      jsonResponse.IDToken,
 		ExpiresOn:    time.Now().Add(time.Duration(jsonResponse.ExpiresIn) * time.Second).Truncate(time.Second),
 		RefreshToken: jsonResponse.RefreshToken,
-		Email:        email,
+		Email:        c.Email,
+		User:         c.Subject,
 	}
 	return
 }
diff --git a/providers/oidc.go b/providers/oidc.go
index fe26ef1d..d751be5e 100644
--- a/providers/oidc.go
+++ b/providers/oidc.go
@@ -128,6 +128,7 @@ func (p *OIDCProvider) createSessionState(ctx context.Context, token *oauth2.Tok
 		RefreshToken: token.RefreshToken,
 		ExpiresOn:    token.Expiry,
 		Email:        claims.Email,
+		User:         claims.Subject,
 	}, nil
 }