/
access_token.go
118 lines (105 loc) · 2.19 KB
/
access_token.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package sso
import (
"encoding/json"
"net/url"
"strconv"
"strings"
)
type AccessTokenResp map[string]interface{}
func NewBearerAccessTokenResp(accessToken string) AccessTokenResp {
return AccessTokenResp{
"token_type": "Bearer",
"access_token": accessToken,
}
}
func (r AccessTokenResp) IDToken() string {
idToken, ok := r["id_token"].(string)
if ok {
return idToken
}
return ""
}
func (r AccessTokenResp) AccessToken() string {
accessToken, ok := r["access_token"].(string)
if ok {
return accessToken
}
return ""
}
func (r AccessTokenResp) ExpiresIn() int {
expires, hasExpires := r["expires"]
expiresIn, hasExpiresIn := r["expires_in"]
// Facebook use "expires" instead of "expires_in"
if hasExpires && !hasExpiresIn {
expiresIn = expires
}
switch v := expiresIn.(type) {
// Azure AD v2 uses string instead of number
case string:
i, err := strconv.Atoi(v)
if err != nil {
return 0
}
return i
case float64:
return int(v)
default:
return 0
}
}
func (r AccessTokenResp) TokenType() string {
tokenType, ok := r["token_type"].(string)
if !ok {
// LinkedIn does not include token_type in the response.
return "Bearer"
}
tokenType = strings.ToLower(tokenType)
switch tokenType {
case "basic":
return "Basic"
case "digest":
return "Digest"
case "bearer":
return "Bearer"
// We do not care about other less common schemes.
default:
return tokenType
}
}
func fetchAccessTokenResp(
client OAuthHTTPClient,
code string,
accessTokenURL string,
redirectURL string,
clientID string,
clientSecret string,
) (r AccessTokenResp, err error) {
v := url.Values{}
v.Set("grant_type", "authorization_code")
v.Add("code", code)
v.Add("redirect_uri", redirectURL)
v.Add("client_id", clientID)
v.Add("client_secret", clientSecret)
// nolint: gosec
resp, err := client.PostForm(accessTokenURL, v)
if resp != nil {
defer resp.Body.Close()
}
if err != nil {
return
}
if resp.StatusCode == 200 {
err = json.NewDecoder(resp.Body).Decode(&r)
if err != nil {
return
}
} else { // normally 400 Bad Request
var errResp oauthErrorResp
err = json.NewDecoder(resp.Body).Decode(&errResp)
if err != nil {
return
}
err = errResp.AsError()
}
return
}