-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcredentials.go
136 lines (120 loc) · 3.47 KB
/
credentials.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
package oauth1
import (
"crypto/rand"
"encoding/hex"
"fmt"
"net/http"
"net/url"
)
// ClientCredentials holds the identifier and shared secret used to
// authenticate a particular client.
type ClientCredentials struct {
ID string
Secret string
// Callback is an optional pre-configured callback URI for the client.
// It is only used if Server.FixedCallbacks is set to true.
Callback *url.URL
// Custom is an extension slot that is not used internally. An
// implementation may optionally use it to store for example the
// application name or author information.
Custom interface{}
}
// TokenCredentials holds the identifier and shared secret used to
// authenticate a resource owner.
type TokenCredentials struct {
ID string
Secret string
ClientID string
// Custom is an extension slot that is not used internally. An
// implementation may optionally use it to store for example a
// user association.
Custom interface{}
}
// WriteTo encodes and writes the identifier and secret to w.
func (t *TokenCredentials) WriteTo(w http.ResponseWriter) error {
w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
v := make(url.Values)
v.Set("oauth_token", t.ID)
v.Set("oauth_token_secret", t.Secret)
_, err := w.Write([]byte(v.Encode()))
return err
}
// TempCredentials holds the identifier and shared secret used to make an
// authorization request to the resource owner.
type TempCredentials struct {
ID string
Secret string
ClientID string
Callback *url.URL
VerificationCode string
// Custom is an extension slot that is not used internally. An
// implementation may optionally use it to store for example a
// user association.
Custom interface{}
}
// WriteTo encodes and writes the identifier and secret to w.
func (t *TempCredentials) WriteTo(w http.ResponseWriter) error {
w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
v := make(url.Values)
v.Set("oauth_token", t.ID)
v.Set("oauth_token_secret", t.Secret)
v.Set("oauth_callback_confirmed", "true")
_, err := w.Write([]byte(v.Encode()))
return err
}
// Redirect replies with a redirect to the callback URL, with identifier and
// verification code added to the query string. It panics if there is no
// callback.
func (t *TempCredentials) Redirect(w http.ResponseWriter, r *http.Request) {
if t.Callback == nil {
panic("missing callback")
}
http.Redirect(w, r, t.verifiedCallback(), http.StatusFound)
}
func (t *TempCredentials) verifiedCallback() string {
u := new(url.URL)
*u = *t.Callback
if u.RawQuery != "" {
u.RawQuery += "&"
}
u.RawQuery += fmt.Sprintf("%s=%s&%s=%s",
tokenIdentifier, url.QueryEscape(t.ID),
verificationCode, url.QueryEscape(t.VerificationCode),
)
return u.String()
}
func newToken(c *ClientCredentials) (*TokenCredentials, error) {
var err error
t := TokenCredentials{ClientID: c.ID}
t.ID, err = randHex(16)
if err != nil {
return nil, err
}
t.Secret, err = randHex(20)
if err != nil {
return nil, err
}
return &t, nil
}
func newTempToken(c *ClientCredentials, callback *url.URL) (*TempCredentials, error) {
tkn, err := newToken(c)
if err != nil {
return nil, err
}
t := TempCredentials{
ID: tkn.ID,
Secret: tkn.Secret,
ClientID: tkn.ClientID,
Callback: callback,
}
t.VerificationCode, err = randHex(20)
if err != nil {
return nil, err
}
return &t, nil
}
func randHex(n int) (string, error) {
b := make([]byte, n)
_, err := rand.Read(b)
return hex.EncodeToString(b), err
}