-
Notifications
You must be signed in to change notification settings - Fork 16
/
config.go
148 lines (124 loc) · 3.49 KB
/
config.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright 2017 Drone.IO Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package oauth2
import (
"encoding/json"
"net/http"
"net/url"
"strings"
"github.com/drone/go-login/login/logger"
)
// token stores the authorization credentials used to
// access protected resources.
type token struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
RefreshToken string `json:"refresh_token"`
Expires int64 `json:"expires_in"`
}
// Config stores the application configuration.
type Config struct {
// HTTP client used to communicate with the authorization
// server. If nil, DefaultClient is used.
Client *http.Client
// ClientID is the identifier issued to the application
// during the registration process.
ClientID string
// ClientSecret is the secret issued to the application
// during the registration process.
ClientSecret string
// Scope is the scope of the access request.
Scope []string
// RedirectURL is used by the authorization server to
// return the authorization credentials to the client.
RedirectURL string
// AccessTokenURL is used by the client to exchange an
// authorization grant for an access token.
AccessTokenURL string
// AuthorizationURL is used by the client to obtain
// authorization from the resource owner.
AuthorizationURL string
// BasicAuthOff instructs the client to disable use of
// the authorization header and provide the client_id
// and client_secret in the formdata.
BasicAuthOff bool
// Logger is used to log errors. If nil the provider
// use the default noop logger.
Logger logger.Logger
// Dumper is used to dump the http.Request and
// http.Response for debug purposes.
Dumper logger.Dumper
}
// authorizeRedirect returns a client authorization
// redirect endpoint.
func (c *Config) authorizeRedirect(state string) string {
v := url.Values{
"response_type": {"code"},
"client_id": {c.ClientID},
}
if len(c.Scope) != 0 {
v.Set("scope", strings.Join(c.Scope, " "))
}
if len(state) != 0 {
v.Set("state", state)
}
if len(c.RedirectURL) != 0 {
v.Set("redirect_uri", c.RedirectURL)
}
u, _ := url.Parse(c.AuthorizationURL)
u.RawQuery = v.Encode()
return u.String()
}
// exchange converts an authorization code into a token.
func (c *Config) exchange(code, state string) (*token, error) {
v := url.Values{
"grant_type": {"authorization_code"},
"code": {code},
}
if c.BasicAuthOff {
v.Set("client_id", c.ClientID)
v.Set("client_secret", c.ClientSecret)
}
if len(state) != 0 {
v.Set("state", state)
}
if len(c.RedirectURL) != 0 {
v.Set("redirect_uri", c.RedirectURL)
}
req, err := http.NewRequest("POST", c.AccessTokenURL, strings.NewReader(v.Encode()))
if err != nil {
return nil, err
}
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
if !c.BasicAuthOff {
req.SetBasicAuth(c.ClientID, c.ClientSecret)
}
if c.Dumper != nil {
c.Dumper.DumpRequest(req)
}
res, err := c.client().Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
if c.Dumper != nil {
c.Dumper.DumpResponse(res)
}
if res.StatusCode > 299 {
err := new(Error)
json.NewDecoder(res.Body).Decode(err)
return nil, err
}
token := &token{}
err = json.NewDecoder(res.Body).Decode(token)
return token, err
}
func (c *Config) client() *http.Client {
client := c.Client
if client == nil {
client = http.DefaultClient
}
return client
}