Fix authentication when using a reverse proxy with subpath prefix (#1818)

* Fix authentication when using a reverse proxy with subpath prefix
This commit is contained in:
InfiniteTF
2021-10-09 08:32:43 +02:00
committed by GitHub
parent 47ae1be53c
commit fb5f9162d0
4 changed files with 29 additions and 17 deletions

View File

@@ -83,12 +83,14 @@ func authenticateHandler() func(http.Handler) http.Handler {
return return
} }
prefix := getProxyPrefix(r.Header)
// otherwise redirect to the login page // otherwise redirect to the login page
u := url.URL{ u := url.URL{
Path: "/login", Path: prefix + "/login",
} }
q := u.Query() q := u.Query()
q.Set(returnURLParam, r.URL.Path) q.Set(returnURLParam, prefix+r.URL.Path)
u.RawQuery = q.Encode() u.RawQuery = q.Encode()
http.Redirect(w, r, u.String(), http.StatusFound) http.Redirect(w, r, u.String(), http.StatusFound)
return return

View File

@@ -147,7 +147,11 @@ func Start(uiBox embed.FS, loginUIBox embed.FS) {
r.HandleFunc("/login*", func(w http.ResponseWriter, r *http.Request) { r.HandleFunc("/login*", func(w http.ResponseWriter, r *http.Request) {
ext := path.Ext(r.URL.Path) ext := path.Ext(r.URL.Path)
if ext == ".html" || ext == "" { if ext == ".html" || ext == "" {
_, _ = w.Write(getLoginPage(loginUIBox)) prefix := getProxyPrefix(r.Header)
data := getLoginPage(loginUIBox)
baseURLIndex := strings.Replace(string(data), "%BASE_URL%", prefix+"/", 2)
_, _ = w.Write([]byte(baseURLIndex))
} else { } else {
r.URL.Path = strings.Replace(r.URL.Path, loginEndPoint, "", 1) r.URL.Path = strings.Replace(r.URL.Path, loginEndPoint, "", 1)
loginRoot, err := fs.Sub(loginUIBox, loginRootDir) loginRoot, err := fs.Sub(loginUIBox, loginRootDir)
@@ -198,11 +202,7 @@ func Start(uiBox embed.FS, loginUIBox embed.FS) {
panic(err) panic(err)
} }
prefix := "" prefix := getProxyPrefix(r.Header)
if r.Header.Get("X-Forwarded-Prefix") != "" {
prefix = strings.TrimRight(r.Header.Get("X-Forwarded-Prefix"), "/")
}
baseURLIndex := strings.Replace(string(data), "%BASE_URL%", prefix+"/", 2) baseURLIndex := strings.Replace(string(data), "%BASE_URL%", prefix+"/", 2)
baseURLIndex = strings.Replace(baseURLIndex, "base href=\"/\"", fmt.Sprintf("base href=\"%s\"", prefix+"/"), 2) baseURLIndex = strings.Replace(baseURLIndex, "base href=\"/\"", fmt.Sprintf("base href=\"%s\"", prefix+"/"), 2)
_, _ = w.Write([]byte(baseURLIndex)) _, _ = w.Write([]byte(baseURLIndex))
@@ -323,10 +323,7 @@ func BaseURLMiddleware(next http.Handler) http.Handler {
} else { } else {
scheme = "http" scheme = "http"
} }
prefix := "" prefix := getProxyPrefix(r.Header)
if r.Header.Get("X-Forwarded-Prefix") != "" {
prefix = strings.TrimRight(r.Header.Get("X-Forwarded-Prefix"), "/")
}
port := "" port := ""
forwardedPort := r.Header.Get("X-Forwarded-Port") forwardedPort := r.Header.Get("X-Forwarded-Port")
@@ -347,3 +344,12 @@ func BaseURLMiddleware(next http.Handler) http.Handler {
} }
return http.HandlerFunc(fn) return http.HandlerFunc(fn)
} }
func getProxyPrefix(headers http.Header) string {
prefix := ""
if headers.Get("X-Forwarded-Prefix") != "" {
prefix = strings.TrimRight(headers.Get("X-Forwarded-Prefix"), "/")
}
return prefix
}

View File

@@ -1,18 +1,19 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<base href="%BASE_URL%">
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Login</title> <title>Login</title>
<link rel="stylesheet" href="/login/login.css"> <link rel="stylesheet" href="login/login.css">
<link rel="stylesheet" href="/css"> <link rel="stylesheet" href="css">
</head> </head>
<body class="login"> <body class="login">
<div class="dialog"> <div class="dialog">
<div class="card"> <div class="card">
<form action="/login" method="POST"> <form action="login" method="POST">
<div class="form-group"> <div class="form-group">
<label for="username"><h6>Username</h6></label> <label for="username"><h6>Username</h6></label>
<input class="text-input form-control" id="username" name="username" type="text" placeholder="Username" /> <input class="text-input form-control" id="username" name="username" type="text" placeholder="Username" />
@@ -36,4 +37,4 @@
</div> </div>
</body> </body>
</html> </html>

View File

@@ -131,7 +131,10 @@ export const createClient = () => {
// handle unauthorized error by redirecting to the login page // handle unauthorized error by redirecting to the login page
if (networkError && (networkError as ServerError).statusCode === 401) { if (networkError && (networkError as ServerError).statusCode === 401) {
// redirect to login page // redirect to login page
const newURL = new URL("/login", window.location.toString()); const newURL = new URL(
`${window.STASH_BASE_URL}login`,
window.location.toString()
);
newURL.searchParams.append("returnURL", window.location.href); newURL.searchParams.append("returnURL", window.location.href);
window.location.href = newURL.toString(); window.location.href = newURL.toString();
} }