feat(web): route unauthenticated root to /welcome, deep links to login

An unauthenticated visit to / now lands on the public /welcome page
instead of bouncing straight to Dex. Deeper guarded paths still redirect
to /auth/login so the post-login round-trip returns the visitor to the
page they asked for. isPublicPath runs first, so no redirect loop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-03 21:48:51 +02:00
co-authored by Claude Opus 4.8
parent d83943c86a
commit 0fdf2f7218
2 changed files with 20 additions and 2 deletions
+14 -2
View File
@@ -161,11 +161,11 @@ func (d *DexAuth) Middleware(h http.Handler) http.Handler {
}
sid, ok := d.sessionID(r)
if !ok {
d.redirectToLogin(w, r)
d.redirectUnauthenticated(w, r)
return
}
if _, ok := d.sessions.get(sid, d.now()); !ok {
d.redirectToLogin(w, r)
d.redirectUnauthenticated(w, r)
return
}
d.sessions.refresh(sid, d.now().Add(d.sessionTTL)) // sliding refresh
@@ -269,6 +269,18 @@ func (d *DexAuth) handleLogout(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, loginPath, http.StatusFound)
}
// redirectUnauthenticated sends an unauthenticated visitor somewhere useful: the
// bare root goes to the public landing page (/welcome), any deeper guarded path
// goes to login so the post-login round-trip can return them to it. isPublicPath
// has already let /welcome and /auth/* through, so this never loops.
func (d *DexAuth) redirectUnauthenticated(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
http.Redirect(w, r, "/welcome", http.StatusFound)
return
}
d.redirectToLogin(w, r)
}
func (d *DexAuth) redirectToLogin(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, loginPath, http.StatusFound)
}
+6
View File
@@ -248,9 +248,15 @@ func TestMiddlewareRedirectsUnauthenticated(t *testing.T) {
w.WriteHeader(http.StatusOK)
}))
// The bare root sends an unauthenticated visitor to the public landing page.
rec := httptest.NewRecorder()
guarded.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/", nil))
require.Equal(t, http.StatusFound, rec.Code)
require.Equal(t, "/welcome", rec.Header().Get("Location"))
// A deeper guarded path goes to login so the post-login round-trip returns there.
rec = httptest.NewRecorder()
guarded.ServeHTTP(rec, httptest.NewRequest(http.MethodGet, "/v/some-id", nil))
require.Equal(t, http.StatusFound, rec.Code)
require.Equal(t, "/auth/login", rec.Header().Get("Location"))
}