Skip to content

Commit 8ba0d36

Browse files
line: added email from id_token (#578)
1 parent 0c63ed9 commit 8ba0d36

File tree

3 files changed

+57
-7
lines changed

3 files changed

+57
-7
lines changed

providers/line/line.go

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ import (
88
"fmt"
99
"io/ioutil"
1010
"net/http"
11+
"time"
1112

13+
"github.com/golang-jwt/jwt/v4"
1214
"github.com/markbates/goth"
1315
"golang.org/x/oauth2"
1416
)
@@ -17,8 +19,14 @@ const (
1719
authURL string = "https://access.line.me/oauth2/v2.1/authorize"
1820
tokenURL string = "https://api.line.me/oauth2/v2.1/token"
1921
endpointUser string = "https://api.line.me/v2/profile"
22+
issuerURL string = "https://access.line.me"
2023
)
2124

25+
type IDTokenClaims struct {
26+
jwt.StandardClaims
27+
Email string `json:"email"`
28+
}
29+
2230
// Provider is the implementation of `goth.Provider` for accessing Line.me.
2331
type Provider struct {
2432
ClientKey string
@@ -95,11 +103,9 @@ func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
95103

96104
response, err := c.Do(req)
97105
if err != nil {
98-
if response != nil {
99-
response.Body.Close()
100-
}
101106
return user, err
102107
}
108+
defer response.Body.Close()
103109

104110
if response.StatusCode != http.StatusOK {
105111
return user, fmt.Errorf("%s responded with a %d trying to fetch user information", p.providerName, response.StatusCode)
@@ -125,6 +131,13 @@ func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
125131
user.NickName = u.DisplayName
126132
user.AvatarURL = u.PictureURL
127133
user.UserID = u.UserID
134+
135+
if sess.IDToken != "" {
136+
if err = p.addDataFromIdToken(sess.IDToken, &user); err != nil {
137+
return user, err
138+
}
139+
}
140+
128141
return user, err
129142
}
130143

@@ -141,9 +154,7 @@ func newConfig(provider *Provider, scopes []string) *oauth2.Config {
141154
}
142155

143156
if len(scopes) > 0 {
144-
for _, scope := range scopes {
145-
c.Scopes = append(c.Scopes, scope)
146-
}
157+
c.Scopes = append(c.Scopes, scopes...)
147158
}
148159
return c
149160
}
@@ -167,3 +178,36 @@ func (p *Provider) SetBotPrompt(botPrompt string) {
167178
}
168179
p.authCodeOptions = append(p.authCodeOptions, oauth2.SetAuthURLParam("bot_prompt", botPrompt))
169180
}
181+
182+
func (p *Provider) addDataFromIdToken(idToken string, user *goth.User) error {
183+
token, err := jwt.ParseWithClaims(idToken, &IDTokenClaims{}, func(t *jwt.Token) (interface{}, error) {
184+
claims := t.Claims.(*IDTokenClaims)
185+
vErr := new(jwt.ValidationError)
186+
187+
if !claims.VerifyAudience(p.ClientKey, true) {
188+
vErr.Inner = fmt.Errorf("audience is incorrect")
189+
vErr.Errors |= jwt.ValidationErrorAudience
190+
}
191+
if !claims.VerifyIssuer(issuerURL, true) {
192+
vErr.Inner = fmt.Errorf("issuer is incorrect")
193+
vErr.Errors |= jwt.ValidationErrorIssuer
194+
}
195+
if !claims.VerifyExpiresAt(time.Now().Unix(), true) {
196+
vErr.Inner = fmt.Errorf("token is expired")
197+
vErr.Errors |= jwt.ValidationErrorExpired
198+
}
199+
if vErr.Errors > 0 {
200+
return nil, vErr
201+
}
202+
203+
return []byte(p.Secret), nil
204+
})
205+
206+
if err != nil {
207+
return err
208+
}
209+
210+
user.Email = token.Claims.(*IDTokenClaims).Email
211+
212+
return nil
213+
}

providers/line/session.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ type Session struct {
1515
AccessToken string
1616
RefreshToken string
1717
ExpiresAt time.Time
18+
IDToken string
1819
}
1920

2021
var _ goth.Session = &Session{}
@@ -42,6 +43,11 @@ func (s *Session) Authorize(provider goth.Provider, params goth.Params) (string,
4243
s.AccessToken = token.AccessToken
4344
s.RefreshToken = token.RefreshToken
4445
s.ExpiresAt = token.Expiry
46+
47+
if idToken := token.Extra("id_token"); idToken != nil {
48+
s.IDToken = idToken.(string)
49+
}
50+
4551
return token.AccessToken, err
4652
}
4753

providers/line/session_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func Test_ToJSON(t *testing.T) {
3636
s := &line.Session{}
3737

3838
data := s.Marshal()
39-
a.Equal(data, `{"AuthURL":"","AccessToken":"","RefreshToken":"","ExpiresAt":"0001-01-01T00:00:00Z"}`)
39+
a.Equal(data, `{"AuthURL":"","AccessToken":"","RefreshToken":"","ExpiresAt":"0001-01-01T00:00:00Z","IDToken":""}`)
4040
}
4141

4242
func Test_String(t *testing.T) {

0 commit comments

Comments
 (0)