forked from elbuo8/oauthio-sdk-go
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathoauth.go
172 lines (156 loc) · 4.35 KB
/
oauth.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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
package oauthio
import (
"encoding/json"
"errors"
"fmt"
"github.com/nu7hatch/gouuid"
"io/ioutil"
"net"
"net/http"
"net/url"
"time"
//"runtime/debug"
)
const (
OAuthdURL = "https://oauth.io"
OAuthdBase = "/auth"
Version = "0.0.1"
)
type OAuth struct {
OAuthdURL string
OAuthdBase string
appKey string
appSecret string
Client *http.Client
}
func timeoutHandler(network, address string) (net.Conn, error) {
return net.DialTimeout(network, address, time.Duration(5*time.Second))
}
func New(appkey, appsecret string) *OAuth {
transport := http.Transport{
Dial: timeoutHandler,
}
return &OAuth{
OAuthdURL: OAuthdURL,
OAuthdBase: OAuthdBase,
appKey: appkey,
appSecret: appsecret,
Client: &http.Client{
Transport: &transport,
},
}
}
func (o *OAuth) GetVersion() string {
return Version
}
func (o *OAuth) SetOAuthdURL(url string) {
o.OAuthdURL = url
}
func (o *OAuth) SetOAuthdBase(url string) {
o.OAuthdBase = url
}
func (o *OAuth) GenerateStateToken() (string, error) {
id, err := uuid.NewV4()
if err != nil {
return "", err
}
return id.String(), nil
}
func (o *OAuth) Redirect(provider string, redirectTo string) func(http.ResponseWriter, *http.Request) {
return func(res http.ResponseWriter, req *http.Request) {
csrf_token, _ := o.GenerateStateToken()
Url, _ := url.Parse(o.OAuthdURL + o.OAuthdBase + "/" + provider)
parameters := url.Values{}
parameters.Add("k", o.appKey)
parameters.Add("opts", "{\"state\":\""+csrf_token+"\"}")
parameters.Add("redirect_type", "server")
parameters.Add("redirect_uri", redirectTo)
Url.RawQuery = parameters.Encode()
fmt.Println(Url.String(), http.StatusFound, csrf_token)
http.Redirect(res, req, Url.String(), http.StatusFound)
}
}
type OAuthResponseData struct {
Code string
}
type OAuthResponse struct {
Status string
Data OAuthResponseData
State string
Provider string
Message string
}
func (o *OAuth) Callback(cb func(*OAuthRequestObject, error, http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
return func(rw http.ResponseWriter, req *http.Request) {
oauthioParam := req.URL.Query()["oauthio"]
if len(oauthioParam) == 0 {
cb(nil, errors.New("oauth.go: Could not get oauthio results."), rw, req)
return
}
r := &OAuthResponse{}
if err := json.Unmarshal([]byte(oauthioParam[0]), r); err != nil {
cb(nil, errors.New("oauth.go: Could not parse oauthio results"), rw, req)
return
}
if r.Status != "success" {
if r.Message != "" {
cb(nil, errors.New("oauth.go: "+r.Message), rw, req)
} else {
cb(nil, errors.New("oauth.go: There is an error in the response"), rw, req)
}
return
}
oauthResp, error := o.Auth(r.Data.Code)
cb(oauthResp, error, rw, req)
}
}
func (o *OAuth) Auth(code string) (*OAuthRequestObject, error) {
data := url.Values{}
data.Set("code", code)
data.Set("key", o.appKey)
data.Set("secret", o.appSecret)
response, err := http.PostForm(o.OAuthdURL+"/auth/access_token", data)
if err != nil {
return nil, errors.New("oauth.go: Couldn't communicate with Oauthd")
}
body, err := ioutil.ReadAll(response.Body)
response.Body.Close()
if err != nil {
return nil, errors.New("oauth.go: Couldn't read Oauthd response")
}
oauthResp := &OAuthRequestObject{}
if err := json.Unmarshal(body, oauthResp); err != nil {
return nil, errors.New("oauth.go: Couldn't parse response")
}
if oauthResp.State == "" {
return nil, errors.New("oauth.go: State is missing in response")
}
oauthResp.ExpireDate = time.Now().Unix() + oauthResp.ExpiresIn
oauthResp.OAuthdURL = o.OAuthdURL
oauthResp.Client = o.Client
oauthResp.appKey = o.appKey
return oauthResp, nil
}
func (o *OAuth) RefreshCredentials(creds *OAuthRequestObject, force bool) error {
if force || time.Now().Unix() > creds.ExpireDate {
data := url.Values{}
data.Set("token", creds.RefreshToken)
data.Set("key", o.appKey)
data.Set("secret", o.appSecret)
response, err := http.PostForm(o.OAuthdURL+"/auth/refresh_token/", data)
if err != nil {
return errors.New("oauth.go: Couldn't communicate with Oauthd")
}
body, err := ioutil.ReadAll(response.Body)
response.Body.Close()
if err != nil {
return errors.New("oauth.go: Couldn't read Oauthd response")
}
err = json.Unmarshal(body, &creds)
if err != nil {
return errors.New("oauth.go: Couldn't parse response")
}
creds.Refreshed = true
}
return nil
}