diff options
Diffstat (limited to 'handlers')
| -rw-r--r-- | handlers/login.go | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/handlers/login.go b/handlers/login.go index 831cd36..6da835a 100644 --- a/handlers/login.go +++ b/handlers/login.go @@ -2,6 +2,7 @@ package handlers import ( "net/http" + "net/url" "text/template" "context" @@ -13,6 +14,7 @@ import ( var loginTmpl = template.Must(template.New("login").Parse(` <!doctype html><title>Login</title> <form method="post" action="/login/submit"> + <input type="hidden" name="next" value="{{.Next}}"> <label>User <input name="username" autocomplete="username"></label><br> <label>Pass <input name="password" type="password" autocomplete="current-password"></label><br> <button>Login</button> @@ -20,15 +22,15 @@ var loginTmpl = template.Must(template.New("login").Parse(` `)) func LoginGET(w http.ResponseWriter, r *http.Request) { - _ = loginTmpl.Execute(w, nil) + _ = loginTmpl.Execute(w, struct{ Next string }{ + Next: r.URL.Query().Get("next"), + }) } - func LoginPOST(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { http.Error(w, "method not allowed", http.StatusMethodNotAllowed) return } - // Parse credentials if err := r.ParseForm(); err != nil { http.Error(w, "bad form", http.StatusBadRequest) return @@ -36,24 +38,35 @@ func LoginPOST(w http.ResponseWriter, r *http.Request) { user := r.Form.Get("username") pass := r.Form.Get("password") - // One-time BSD Auth (OpenBSD's BSD Authentication, not PAM) ok, _ := bsdauth.Authenticate(user, pass, "auth-myapp") - // `auth_userokay()` returns nonzero on success. :contentReference[oaicite:2]{index=2} if !ok { http.Error(w, "invalid credentials", http.StatusUnauthorized) return } - // Rotate session token to prevent fixation, then set user if err := session.Manager.RenewToken(r.Context()); err != nil { http.Error(w, "server error", http.StatusInternalServerError) return } session.Manager.Put(r.Context(), "user", user) - http.Redirect(w, r, "/", http.StatusSeeOther) -} + // Prefer ?next=... when present, but guard against open redirects. + next := r.Form.Get("next") + if next == "" { + next = "/" + } else { + u, err := url.Parse(next) + if err != nil || u.IsAbs() || len(u.Host) > 0 { + next = "/" + } + // Optional: only allow same-site paths + if u.Path == "" || u.Path[0] != '/' { + next = "/" + } + } + http.Redirect(w, r, next, http.StatusSeeOther) // PRG pattern +} func LogoutPOST(w http.ResponseWriter, r *http.Request) { _ = session.Manager.Destroy(r.Context()) http.Redirect(w, r, "/login", http.StatusSeeOther) |
