diff --git a/internal/web/oidc/oidc.go b/internal/web/oidc/oidc.go index d42a5c1..55e1c3a 100644 --- a/internal/web/oidc/oidc.go +++ b/internal/web/oidc/oidc.go @@ -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) } diff --git a/internal/web/oidc/oidc_test.go b/internal/web/oidc/oidc_test.go index 889aa80..d1614a0 100644 --- a/internal/web/oidc/oidc_test.go +++ b/internal/web/oidc/oidc_test.go @@ -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")) }