Feature: Group handling
This commit is contained in:
parent
2d8643d593
commit
22af9254a5
23
main.go
23
main.go
|
@ -28,6 +28,7 @@ type Config struct {
|
||||||
SsoUriPtr *string
|
SsoUriPtr *string
|
||||||
BasicAuthPtr *string
|
BasicAuthPtr *string
|
||||||
UsernameHeaderPtr *string
|
UsernameHeaderPtr *string
|
||||||
|
GroupsHeaderPtr *string
|
||||||
CookieSecret string
|
CookieSecret string
|
||||||
AllowAllPtr *bool
|
AllowAllPtr *bool
|
||||||
}
|
}
|
||||||
|
@ -43,6 +44,7 @@ func main() {
|
||||||
config.AllowAllPtr = flag.Bool("allow-all", false, "allow all discourse users (default: admin users only)")
|
config.AllowAllPtr = flag.Bool("allow-all", false, "allow all discourse users (default: admin users only)")
|
||||||
config.BasicAuthPtr = flag.String("basic-auth", "", "HTTP Basic authentication credentials to let through directly")
|
config.BasicAuthPtr = flag.String("basic-auth", "", "HTTP Basic authentication credentials to let through directly")
|
||||||
config.UsernameHeaderPtr = flag.String("username-header", "Discourse-User-Name", "Request header to pass authenticated username into")
|
config.UsernameHeaderPtr = flag.String("username-header", "Discourse-User-Name", "Request header to pass authenticated username into")
|
||||||
|
config.GroupsHeaderPtr = flag.String("groups-header", "Discourse-User-Groups", "Request header to pass authenticated groups into")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
|
@ -136,14 +138,15 @@ func checkAuthorizationHeader(handler http.Handler, r *http.Request, w http.Resp
|
||||||
|
|
||||||
func redirectIfNoCookie(handler http.Handler, r *http.Request, w http.ResponseWriter, config *Config) {
|
func redirectIfNoCookie(handler http.Handler, r *http.Request, w http.ResponseWriter, config *Config) {
|
||||||
cookie, err := r.Cookie("__discourse_proxy")
|
cookie, err := r.Cookie("__discourse_proxy")
|
||||||
var username string
|
var username, groups string
|
||||||
|
|
||||||
if err == nil && cookie != nil {
|
if err == nil && cookie != nil {
|
||||||
username, err = parseCookie(cookie.Value, config.CookieSecret)
|
username, groups, err = parseCookie(cookie.Value, config.CookieSecret)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
r.Header.Set(*config.UsernameHeaderPtr, username)
|
r.Header.Set(*config.UsernameHeaderPtr, username)
|
||||||
|
r.Header.Set(*config.GroupsHeaderPtr, groups)
|
||||||
handler.ServeHTTP(w, r)
|
handler.ServeHTTP(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -161,10 +164,11 @@ func redirectIfNoCookie(handler http.Handler, r *http.Request, w http.ResponseWr
|
||||||
parsedQuery, _ := url.ParseQuery(decodedString)
|
parsedQuery, _ := url.ParseQuery(decodedString)
|
||||||
|
|
||||||
username := parsedQuery["username"]
|
username := parsedQuery["username"]
|
||||||
|
groups := parsedQuery["groups"]
|
||||||
admin := parsedQuery["admin"]
|
admin := parsedQuery["admin"]
|
||||||
nonce := parsedQuery["nonce"]
|
nonce := parsedQuery["nonce"]
|
||||||
|
|
||||||
if len(nonce) > 0 && len(admin) > 0 && len(username) > 0 && admin[0] == "true" {
|
if len(nonce) > 0 && len(admin) > 0 && len(username) > 0 && (admin[0] == "true" || *config.AllowAllPtr) {
|
||||||
returnUrl, err := getReturnUrl(*config.SsoSecretPtr, sso, sig, nonce[0])
|
returnUrl, err := getReturnUrl(*config.SsoSecretPtr, sso, sig, nonce[0])
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -175,7 +179,8 @@ func redirectIfNoCookie(handler http.Handler, r *http.Request, w http.ResponseWr
|
||||||
// we have a valid auth
|
// we have a valid auth
|
||||||
expiration := time.Now().Add(365 * 24 * time.Hour)
|
expiration := time.Now().Add(365 * 24 * time.Hour)
|
||||||
|
|
||||||
cookie := http.Cookie{Name: "__discourse_proxy", Value: signCookie(username[0], config.CookieSecret), Expires: expiration, HttpOnly: true}
|
cookieData := strings.Join([]string{username[0], strings.Join(groups, "|")}, ",")
|
||||||
|
cookie := http.Cookie{Name: "__discourse_proxy", Value: signCookie(cookieData, config.CookieSecret), Expires: expiration, HttpOnly: true}
|
||||||
http.SetCookie(w, &cookie)
|
http.SetCookie(w, &cookie)
|
||||||
|
|
||||||
// works around weird safari stuff
|
// works around weird safari stuff
|
||||||
|
@ -209,9 +214,10 @@ func signCookie(data, secret string) string {
|
||||||
return data + "," + ComputeHmac256(data, secret)
|
return data + "," + ComputeHmac256(data, secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseCookie(data, secret string) (parsed string, err error) {
|
func parseCookie(data, secret string) (username string, groups string, err error) {
|
||||||
err = nil
|
err = nil
|
||||||
parsed = ""
|
username = ""
|
||||||
|
groups = ""
|
||||||
|
|
||||||
split := strings.Split(data, ",")
|
split := strings.Split(data, ",")
|
||||||
|
|
||||||
|
@ -221,13 +227,16 @@ func parseCookie(data, secret string) (parsed string, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
signature := split[len(split)-1]
|
signature := split[len(split)-1]
|
||||||
parsed = strings.Join(split[:len(split)-1], ",")
|
parsed := strings.Join(split[:len(split)-1], ",")
|
||||||
expected := ComputeHmac256(parsed, secret)
|
expected := ComputeHmac256(parsed, secret)
|
||||||
|
|
||||||
if expected != signature {
|
if expected != signature {
|
||||||
parsed = ""
|
parsed = ""
|
||||||
err = fmt.Errorf("Expecting signature to match")
|
err = fmt.Errorf("Expecting signature to match")
|
||||||
return
|
return
|
||||||
|
} else {
|
||||||
|
username = strings.Split(parsed, ",")[0]
|
||||||
|
groups = strings.Split(parsed, ",")[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue