-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
142 lines (122 loc) · 3.82 KB
/
main.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
package main
import (
"encoding/json"
"net/http"
"github.com/gin-gonic/gin"
"github.com/parnurzeal/gorequest"
log "github.com/sirupsen/logrus"
)
const (
clientID = "e492eaede804e5ac89e2"
clientSecret = "3ce3a35daec317529b6f6157cd65456581b94039"
accessTokenURI = "https://github.com/login/oauth/access_token"
userURI = "https://api.github.com/user"
)
func main() {
router := gin.Default()
router.LoadHTMLGlob("frontend/*")
router.GET("/", IndexHandler)
router.GET("/oauth/redirect", OAuthHandler)
router.Run(":8080")
}
// IndexHandler index handler for /
func IndexHandler(c *gin.Context) {
// 1. Request a user's GitHub identity
// GET https://github.com/login/oauth/authorize
c.HTML(http.StatusOK, "index.tmpl", nil)
}
// OAuthHandler oauth handler for /oauth/redirect
// https://developer.github.com/apps/building-oauth-apps/authorizing-oauth-apps/
func OAuthHandler(c *gin.Context) {
// 2. Users are redirected back to your site by GitHub
// GET http://localhost:8080/oauth/redirect
oauthCode := c.Query("code")
log.WithField("oauthCode", oauthCode).Infoln("oauthCode info")
if oauthCode == "" {
log.Error("OAuth failed: the oauth code from github invalid")
c.HTML(http.StatusInternalServerError, "err.tmpl", gin.H{
"code": http.StatusInternalServerError,
"err": "Invalid oauth code",
})
return
}
// 3. Exchange this code for an access token
// POST https://github.com/login/oauth/access_token
log.Infoln("start access token...")
_, body, errs := gorequest.New().Post(accessTokenURI).
Param("client_id", clientID).
Param("client_secret", clientSecret).
Param("code", oauthCode).
Set("accept", "application/json").
End()
if len(errs) > 0 {
log.WithField("errs", errs).Error("access token failed")
c.HTML(http.StatusInternalServerError, "err.tmpl", gin.H{
"code": http.StatusInternalServerError,
"err": errs,
})
return
}
log.WithField("body", body).Infoln("access token info")
bodyMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(body), &bodyMap); err != nil {
log.WithField("body", body).WithError(err).Error("json unmarshal body failed")
c.HTML(http.StatusInternalServerError, "err.tmpl", gin.H{
"code": http.StatusInternalServerError,
"err": err,
})
return
}
accessToken, ok := bodyMap["access_token"].(string)
if !ok {
log.WithFields(log.Fields{
"accessToken": accessToken,
"ok": ok,
}).Error("parse access token failed")
c.HTML(http.StatusInternalServerError, "err.tmpl", gin.H{
"code": http.StatusInternalServerError,
"err": "parse access token failed",
})
return
}
// 4. Use the access token to access the API
// GET https://api.github.com/user
log.Infoln("start access user api...")
_, body, errs = gorequest.New().Get(userURI).
Set("Authorization", "token "+accessToken).
Set("accept", "application/json").
End()
if len(errs) > 0 {
log.WithField("errs", errs).Error("get user info failed")
c.HTML(http.StatusInternalServerError, "err.tmpl", gin.H{
"code": http.StatusInternalServerError,
"err": errs,
})
return
}
log.WithField("body", body).Infoln("user info")
userBodyMap := make(map[string]interface{})
if err := json.Unmarshal([]byte(body), &userBodyMap); err != nil {
log.WithField("body", body).WithError(err).Errorln("json unmarshal user body failed")
c.HTML(http.StatusInternalServerError, "err.tmpl", gin.H{
"code": http.StatusInternalServerError,
"err": err,
})
return
}
userName, ok := userBodyMap["name"].(string)
if !ok {
log.WithFields(log.Fields{
"userName": userName,
"ok": ok,
}).Error("parse user name failed")
c.HTML(http.StatusInternalServerError, "err.tmpl", gin.H{
"code": http.StatusInternalServerError,
"err": "parse user name failed",
})
return
}
c.HTML(http.StatusOK, "welcome.tmpl", gin.H{
"userName": userName,
})
}