-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgithub.go
134 lines (117 loc) · 3.37 KB
/
github.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
package main
import (
"net/http"
"github.com/google/go-github/github"
"golang.org/x/oauth2"
)
func githubLogin(w http.ResponseWriter, r *http.Request) {
session, err := cookies.Get(r, "_oauthState")
if err != nil && err.Error() != "securecookie: the value is not valid" {
log.Error(err.Error())
sendError(w, http.StatusInternalServerError)
return
}
stateString, err := cryptogen(32)
if err != nil {
log.Error(err.Error())
sendError(w, http.StatusInternalServerError)
return
}
session.Values["github"] = stateString
err = session.Save(r, w)
if err != nil {
log.Error(err.Error())
sendError(w, http.StatusInternalServerError)
return
}
url := configGithub.AuthCodeURL(stateString)
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}
func githubCallback(w http.ResponseWriter, r *http.Request) {
session, err := cookies.Get(r, "_oauthState")
if err != nil {
log.Error(err.Error())
sendError(w, http.StatusInternalServerError)
return
}
state := session.Values["github"]
var expectedState string
var ok bool
if expectedState, ok = state.(string); !ok {
log.Error("couldn't get expectedState from cookie _oauthState.github")
sendError(w, http.StatusInternalServerError)
return
}
actualState := r.FormValue("state")
if actualState != expectedState {
log.Warningf("couldn't authenticate user: actualState(%s) and expectedState(%s) don't match. login denied", actualState, expectedState)
w.WriteHeader(http.StatusForbidden)
return
}
code := r.FormValue("code")
token, err := configGithub.Exchange(oauth2.NoContext, code)
if err != nil {
log.Error(err.Error())
sendError(w, http.StatusInternalServerError)
return
}
httpClient := configGithub.Client(oauth2.NoContext, token)
client := github.NewClient(httpClient)
githubUser, _, err := client.Users.Get(oauth2.NoContext, "")
if err != nil {
log.Error(err.Error())
sendError(w, http.StatusInternalServerError)
return
}
authorized := false
// If no authentication method is defined set authorized to true and continue
if !config.ACP.Whitelist && !config.ACP.Org {
authorized = true
} else {
// Query whitelisted persons
if config.ACP.Whitelist {
for _, entry := range whitelist {
if entry == *githubUser.ID {
authorized = true
break
}
}
}
// Check if the the user is a member of a specific organization to enable
// SSO functionality
if config.ACP.Org {
orgs, _, err := client.Organizations.List(oauth2.NoContext, "", nil)
if err != nil {
log.Warningf("login: github(%d).Orgs.List returned: %s", *githubUser.ID, err.Error())
} else {
for _, item := range orgs {
if *item.Login == config.ACP.OrgName {
authorized = true
break
}
}
}
}
}
// Send forbidden pages to unauthorized users and log their github id
if !authorized {
log.Infof("login: github(%d) -> not authorized", *githubUser.ID)
sendError(w, http.StatusForbidden)
return
}
// If user is already logged in delete the old key
if k, exists := userKey[*githubUser.ID]; exists {
delete(keyUser, k)
delete(userKey, *githubUser.ID)
}
key, err := cryptogen(32)
if err != nil {
log.Error(err.Error())
sendError(w, http.StatusInternalServerError)
return
}
keyUser[key] = *githubUser.ID
userKey[*githubUser.ID] = key
log.Infof("login: github(%d) -> %s", *githubUser.ID, key)
http.Redirect(w, r, "/f/"+key+"/", http.StatusTemporaryRedirect)
}