/
config_provider.go
121 lines (98 loc) · 2.88 KB
/
config_provider.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
package oauth2providers
import (
"context"
"errors"
"net/http"
"golang.org/x/oauth2"
)
var (
// ErrMissingClientID is returned when the client ID is missing.
ErrMissingClientID = errors.New("missing client ID")
// ErrMissingClientSecret is returned when the client secret is missing.
ErrMissingClientSecret = errors.New("missing client secret")
// ErrMissingRedirectURL is returned when the redirect URL is missing.
ErrMissingRedirectURL = errors.New("missing redirect URL")
)
type ProviderConfig interface {
AuthCodeURL(state string, opts ...AuthCodeOption) string
Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error)
TokenSource(ctx context.Context, token *Token) oauth2.TokenSource
Client(ctx context.Context, token *Token) *http.Client
addScopes(scopes ...string)
setAuthURL(authURL string)
setTokenURL(tokenURL string)
}
type providerConfig struct {
authURL string
tokenURL string
scopes []string
clientID string
clientSecret string
redirectURL string
oauth2.Config
}
func validateProviderConfig(pc *providerConfig) error {
if pc.clientID == "" {
return ErrMissingClientID
}
if pc.clientSecret == "" {
return ErrMissingClientSecret
}
if pc.redirectURL == "" {
return ErrMissingRedirectURL
}
return nil
}
func NewProviderConfig(opts ...ProviderOption) (ProviderConfig, error) {
pc := &providerConfig{}
for _, opt := range opts {
opt(pc)
}
if err := validateProviderConfig(pc); err != nil {
return nil, err
}
pc.Config = oauth2.Config{
ClientID: pc.clientID,
ClientSecret: pc.clientSecret,
RedirectURL: pc.redirectURL,
Scopes: pc.scopes,
Endpoint: oauth2.Endpoint{
AuthURL: pc.authURL,
TokenURL: pc.tokenURL,
},
}
return pc, nil
}
func (pc *providerConfig) AuthCodeURL(state string, opts ...AuthCodeOption) string {
return pc.Config.AuthCodeURL(state, convertAuthCodeOptions(opts)...)
}
func (pc *providerConfig) Exchange(ctx context.Context, code string, opts ...AuthCodeOption) (*Token, error) {
return pc.Config.Exchange(ctx, code, convertAuthCodeOptions(opts)...)
}
func (pc *providerConfig) TokenSource(ctx context.Context, token *Token) oauth2.TokenSource {
return pc.Config.TokenSource(ctx, token)
}
func (pc *providerConfig) Client(ctx context.Context, token *Token) *http.Client {
return pc.Config.Client(ctx, token)
}
func (pc *providerConfig) addScopes(scopes ...string) {
hasSeen := map[string]bool{}
for _, scope := range pc.scopes {
hasSeen[scope] = true
}
for _, scope := range scopes {
if _, ok := hasSeen[scope]; !ok {
pc.scopes = append(pc.scopes, scope)
hasSeen[scope] = true
}
}
pc.Config.Scopes = pc.scopes
}
func (pc *providerConfig) setAuthURL(authURL string) {
pc.authURL = authURL
pc.Config.Endpoint.AuthURL = authURL
}
func (pc *providerConfig) setTokenURL(tokenURL string) {
pc.tokenURL = tokenURL
pc.Config.Endpoint.TokenURL = tokenURL
}