mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-08-06 21:28:30 +02:00
feat(sso): forward auth improvements
This adds a couple of key improvements to the Forward Auth SSO implementation. Primarily it adds an included cookies setting which allows filtering cookies to the authorization server. Secondly it fixes a bug where the headerCopyIncluded function was case-sensitive. Documentation in the code and on the web UI is clearer to resolve some common questions and issues. Lastly it moves a lot of funcs to the util.go file and adds fairly comprehensive tests.
This commit is contained in:
137
src/mod/auth/sso/forward/util.go
Normal file
137
src/mod/auth/sso/forward/util.go
Normal file
@@ -0,0 +1,137 @@
|
||||
package forward
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func scheme(r *http.Request) string {
|
||||
if r.TLS != nil {
|
||||
return "https"
|
||||
}
|
||||
|
||||
return "http"
|
||||
}
|
||||
|
||||
func headerCookieRedact(r *http.Request, names []string, exclude bool) {
|
||||
if len(names) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
original := r.Cookies()
|
||||
|
||||
if len(original) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
var cookies []string
|
||||
|
||||
for _, cookie := range original {
|
||||
if exclude && stringInSlice(cookie.Name, names) {
|
||||
continue
|
||||
} else if !exclude && !stringInSlice(cookie.Name, names) {
|
||||
continue
|
||||
}
|
||||
|
||||
cookies = append(cookies, cookie.String())
|
||||
}
|
||||
|
||||
value := strings.Join(cookies, "; ")
|
||||
|
||||
r.Header.Set(HeaderCookie, value)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func headerCopyExcluded(original, destination http.Header, excludedHeaders []string) {
|
||||
for key, values := range original {
|
||||
// We should never copy the headers in the below list.
|
||||
if stringInSliceFold(key, doNotCopyHeaders) {
|
||||
continue
|
||||
}
|
||||
|
||||
if stringInSliceFold(key, excludedHeaders) {
|
||||
continue
|
||||
}
|
||||
|
||||
destination[key] = append(destination[key], values...)
|
||||
}
|
||||
}
|
||||
|
||||
func headerCopyIncluded(original, destination http.Header, includedHeaders []string, allIfEmpty bool) {
|
||||
if allIfEmpty && len(includedHeaders) == 0 {
|
||||
headerCopyAll(original, destination)
|
||||
} else {
|
||||
headerCopyIncludedExact(original, destination, includedHeaders)
|
||||
}
|
||||
}
|
||||
|
||||
func headerCopyAll(original, destination http.Header) {
|
||||
for key, values := range original {
|
||||
// We should never copy the headers in the below list, even if they're in the list provided by a user.
|
||||
if stringInSliceFold(key, doNotCopyHeaders) {
|
||||
continue
|
||||
}
|
||||
|
||||
destination[key] = append(destination[key], values...)
|
||||
}
|
||||
}
|
||||
|
||||
func headerCopyIncludedExact(original, destination http.Header, keys []string) {
|
||||
for key, values := range original {
|
||||
// We should never copy the headers in the below list, even if they're in the list provided by a user.
|
||||
if stringInSliceFold(key, doNotCopyHeaders) {
|
||||
continue
|
||||
}
|
||||
|
||||
if !stringInSliceFold(key, keys) {
|
||||
continue
|
||||
}
|
||||
|
||||
destination[key] = append(destination[key], values...)
|
||||
}
|
||||
}
|
||||
|
||||
func stringInSlice(needle string, haystack []string) bool {
|
||||
if len(haystack) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, v := range haystack {
|
||||
if needle == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func stringInSliceFold(needle string, haystack []string) bool {
|
||||
if len(haystack) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, v := range haystack {
|
||||
if strings.EqualFold(needle, v) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func rSetForwardedHeaders(r, req *http.Request) {
|
||||
if r.RemoteAddr != "" {
|
||||
before, _, _ := strings.Cut(r.RemoteAddr, ":")
|
||||
|
||||
if ip := net.ParseIP(before); ip != nil {
|
||||
req.Header.Set(HeaderXForwardedFor, ip.String())
|
||||
}
|
||||
}
|
||||
|
||||
req.Header.Set(HeaderXForwardedMethod, r.Method)
|
||||
req.Header.Set(HeaderXForwardedProto, scheme(r))
|
||||
req.Header.Set(HeaderXForwardedHost, r.Host)
|
||||
req.Header.Set(HeaderXForwardedURI, r.URL.Path)
|
||||
}
|
Reference in New Issue
Block a user