pull/3884/merge
jake-dog 2025-06-28 08:40:40 +02:00 committed by GitHub
commit f0d4e830f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 41 additions and 5 deletions

View File

@ -38,6 +38,8 @@ func addConfigFlags(flags *pflag.FlagSet) {
flags.String("auth.header", "", "HTTP header for auth.method=proxy")
flags.String("auth.command", "", "command for auth.method=hook")
flags.String("logoutpage", "", "custom logout page")
flags.String("recaptcha.host", "https://www.google.com", "use another host for ReCAPTCHA. recaptcha.net might be useful in China")
flags.String("recaptcha.key", "", "ReCaptcha site key")
flags.String("recaptcha.secret", "", "ReCaptcha secret")
@ -145,6 +147,7 @@ func printSettings(ser *settings.Server, set *settings.Settings, auther auth.Aut
fmt.Fprintf(w, "Sign up:\t%t\n", set.Signup)
fmt.Fprintf(w, "Create User Dir:\t%t\n", set.CreateUserDir)
fmt.Fprintf(w, "Auth method:\t%s\n", set.AuthMethod)
fmt.Fprintf(w, "LogoutPage:\t%s\n", set.LogoutPage)
fmt.Fprintf(w, "Shell:\t%s\t\n", strings.Join(set.Shell, " "))
fmt.Fprintln(w, "\nBranding:")
fmt.Fprintf(w, "\tName:\t%s\n", set.Branding.Name)

View File

@ -47,6 +47,8 @@ you want to change. Other options will remain unchanged.`,
set.Signup = mustGetBool(flags, flag.Name)
case "auth.method":
hasAuth = true
case "logoutpage":
set.LogoutPage = mustGetString(flags, flag.Name)
case "shell":
set.Shell = convertCmdStrToCmdArray(mustGetString(flags, flag.Name))
case "create-user-dir":

View File

@ -56,6 +56,7 @@
DisableUsedPercentage: false,
EnableExec: true,
EnableThumbs: true,
LogoutPage: "",
LoginPage: true,
Name: "",
NoAuth: false,

View File

@ -124,6 +124,7 @@ import {
disableExternal,
disableUsedPercentage,
noAuth,
logoutPage,
loginPage,
} from "@/utils/constants";
import { files as api } from "@/api";
@ -153,7 +154,7 @@ export default {
version: () => version,
disableExternal: () => disableExternal,
disableUsedPercentage: () => disableUsedPercentage,
canLogout: () => !noAuth && loginPage,
canLogout: () => !noAuth && (loginPage || logoutPage !== "/login"),
},
methods: {
...mapActions(useLayoutStore, ["closeHovers", "showHover"]),

View File

@ -2,7 +2,7 @@ import { useAuthStore } from "@/stores/auth";
import router from "@/router";
import type { JwtPayload } from "jwt-decode";
import { jwtDecode } from "jwt-decode";
import { baseURL, noAuth } from "./constants";
import { baseURL, noAuth, logoutPage } from "./constants";
import { StatusError } from "@/api/utils";
export function parseToken(token: string) {
@ -101,6 +101,8 @@ export function logout() {
localStorage.setItem("jwt", "");
if (noAuth) {
window.location.reload();
} else if (logoutPage !== "/login") {
document.location.href = `${logoutPage}`;
} else {
router.push({ path: "/login" });
}

View File

@ -10,6 +10,7 @@ const version: string = window.FileBrowser.Version;
const logoURL = `${staticURL}/img/logo.svg`;
const noAuth: boolean = window.FileBrowser.NoAuth;
const authMethod = window.FileBrowser.AuthMethod;
const logoutPage: string = window.FileBrowser.LogoutPage || "/login";
const loginPage: boolean = window.FileBrowser.LoginPage;
const theme: UserTheme = window.FileBrowser.Theme;
const enableThumbs: boolean = window.FileBrowser.EnableThumbs;
@ -31,6 +32,7 @@ export {
version,
noAuth,
authMethod,
logoutPage,
loginPage,
theme,
enableThumbs,

View File

@ -12,7 +12,9 @@ import (
"github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/v4/request"
fbAuth "github.com/filebrowser/filebrowser/v2/auth"
fbErrors "github.com/filebrowser/filebrowser/v2/errors"
"github.com/filebrowser/filebrowser/v2/settings"
"github.com/filebrowser/filebrowser/v2/users"
)
@ -64,6 +66,20 @@ func (e extractor) ExtractToken(r *http.Request) (string, error) {
return "", request.ErrNoTokenInRequest
}
func renewableErr(err error, d *data) bool {
if d.settings.AuthMethod != fbAuth.MethodProxyAuth || err == nil {
return false
}
if d.settings.LogoutPage == "" || d.settings.LogoutPage == settings.DefaultLogoutPage {
return false
}
var verr *jwt.ValidationError
if !errors.As(err, &verr) || verr == nil || verr.Errors != jwt.ValidationErrorExpired {
return false
}
return true
}
func withUser(fn handleFunc) handleFunc {
return func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
keyFunc := func(_ *jwt.Token) (interface{}, error) {
@ -71,9 +87,10 @@ func withUser(fn handleFunc) handleFunc {
}
var tk authToken
token, err := request.ParseFromRequest(r, &extractor{}, keyFunc, request.WithClaims(&tk))
p := jwt.NewParser(jwt.WithValidMethods([]string{jwt.SigningMethodHS256.Alg()}))
token, err := request.ParseFromRequest(r, &extractor{}, keyFunc, request.WithClaims(&tk), request.WithParser(p))
if err != nil || !token.Valid {
if (err != nil || !token.Valid) && !renewableErr(err, d) {
return http.StatusUnauthorized, nil
}

View File

@ -38,6 +38,7 @@ func handleWithStaticData(w http.ResponseWriter, _ *http.Request, d *data, fSys
"Signup": d.settings.Signup,
"NoAuth": d.settings.AuthMethod == auth.MethodNoAuth,
"AuthMethod": d.settings.AuthMethod,
"LogoutPage": d.settings.LogoutPage,
"LoginPage": auther.LoginPage(),
"CSS": false,
"ReCaptcha": false,

View File

@ -9,7 +9,10 @@ import (
"github.com/filebrowser/filebrowser/v2/rules"
)
const DefaultUsersHomeBasePath = "/users"
const (
DefaultLogoutPage = "/login"
DefaultUsersHomeBasePath = "/users"
)
// AuthMethod describes an authentication method.
type AuthMethod string
@ -22,6 +25,7 @@ type Settings struct {
UserHomeBasePath string `json:"userHomeBasePath"`
Defaults UserDefaults `json:"defaults"`
AuthMethod AuthMethod `json:"authMethod"`
LogoutPage string `json:"logoutPage"`
Branding Branding `json:"branding"`
Tus Tus `json:"tus"`
Commands map[string][]string `json:"commands"`

View File

@ -33,6 +33,9 @@ func (s *Storage) Get() (*Settings, error) {
if set.UserHomeBasePath == "" {
set.UserHomeBasePath = DefaultUsersHomeBasePath
}
if set.LogoutPage == "" {
set.LogoutPage = DefaultLogoutPage
}
if set.Tus == (Tus{}) {
set.Tus = Tus{
ChunkSize: DefaultTusChunkSize,