forked from bradrydzewski/go.auth
-
Notifications
You must be signed in to change notification settings - Fork 0
/
oauth1.go
132 lines (107 loc) · 3.37 KB
/
oauth1.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
package auth
import (
"encoding/json"
"io/ioutil"
"net/http"
"net/url"
"github.com/bradrydzewski/go.auth/oauth1"
)
// Abstract implementation of OAuth2 for user authentication.
type OAuth1Mixin struct {
oauth1.Consumer
}
// Redirect will do an http.Redirect, sending the user to the Provider's
// login screen.
func (self *OAuth1Mixin) Redirect(w http.ResponseWriter, r *http.Request) {
if err := self.AuthorizeRedirect(w, r, self.Consumer.AuthorizationURL); err != nil {
println("Error redirecting to authorization endpoint: " + err.Error())
}
}
// RedirectRequired returns a boolean value indicating if the request should
// be redirected to the Provider's login screen, in order to provide an OAuth
// Verifier Token.
func (self *OAuth1Mixin) RedirectRequired(r *http.Request) bool {
return r.URL.Query().Get("oauth_verifier") == ""
}
// Redirects the User to the OAuth1.0a provider's Login Screen. A RequestToken
// is requested from the Provider, and included in the URL's oauth_token param.
//
// A Successful Login / Authorization should return both the oauth_token and
// the oauth_verifier to the callback URL.
func (self *OAuth1Mixin) AuthorizeRedirect(w http.ResponseWriter, r *http.Request, endpoint string) error {
//Get a Request Token
token, err := self.Consumer.RequestToken()
if err != nil {
return err
}
//Get the redirect URL
url, err := self.Consumer.AuthorizeRedirect(token)
if err != nil {
return err
}
//Write the Request Token to a Cookie, so that we can
//retrieve it after re-directing the user to the
//providers authorization screen.
cookie := http.Cookie{}
cookie.Name = "_token"
cookie.Path = "/"
cookie.Domain = r.URL.Host
cookie.HttpOnly = true
cookie.Secure = Config.CookieSecure
cookie.Value = token.Encode()
http.SetCookie(w, &cookie)
// redirect to the login url
http.Redirect(w, r, url, http.StatusSeeOther)
return nil
}
// AuthorizeToken trades the Verification Code (oauth_verification) for an
// Access Token.
func (self *OAuth1Mixin) AuthorizeToken(w http.ResponseWriter, r *http.Request) (*oauth1.AccessToken, error) {
//Get the presisted request token
cookie, err := r.Cookie("_token")
if err != nil {
return nil, nil
}
//Parse the persisted request token
requestToken, err := oauth1.ParseRequestTokenStr(cookie.Value)
if err != nil {
return nil, err
}
//Delete the request Token ...don't need it anymore
DeleteUserCookieName(w,r,"_token")
//Parse the verification code from the Redirect URL
verifier := r.URL.Query().Get("oauth_verifier")
//Upgrade to an Authorization Token
accessToken, err := self.Consumer.AuthorizeToken(requestToken, verifier)
if err != nil {
return nil, err
}
return accessToken, nil
}
func (self *OAuth1Mixin) GetAuthenticatedUser(endpoint string, token *oauth1.AccessToken, resp interface{}) error {
//create the user url
endpointUrl, _ := url.Parse(endpoint)
//create the http request for the user Url
req := http.Request{
URL: endpointUrl,
Method: "GET",
ProtoMajor: 1,
ProtoMinor: 1,
Close: true,
}
//sign the request with the access token
self.Sign(&req, token)
//do the http request and get the response
r, err := http.DefaultClient.Do(&req)
if err != nil {
return err
}
//get the response body
userData, err := ioutil.ReadAll(r.Body)
defer r.Body.Close()
if err != nil {
return err
}
//unmarshal user json
return json.Unmarshal(userData, &resp)
}