From 3af104915f01aa337cc095e58b8b38186bd33526 Mon Sep 17 00:00:00 2001 From: Tyler Gillispie Date: Fri, 28 Aug 2026 00:17:34 -0700 Subject: [PATCH] fix(auth): redirect authenticated sessions from / and /login to /dashboard --- src/features/auth/login_routes.ts | 17 +++++++++++++++-- src/features/auth/register_routes.ts | 8 ++++++-- src/main.ts | 6 +++++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/features/auth/login_routes.ts b/src/features/auth/login_routes.ts index e38333f..0231a2d 100644 --- a/src/features/auth/login_routes.ts +++ b/src/features/auth/login_routes.ts @@ -9,7 +9,12 @@ import type { AuthenticationResponseJSON } from "jsr:@simplewebauthn/server@13"; import { valkey } from "../../core/valkey.ts"; import { getClientIp, publicRateLimiter } from "../../core/middleware.ts"; -import { extractAllSessionIds, getCookieDomain } from "../../core/session.ts"; +import { + extractAllSessionIds, + getAuthenticatedUser, + getCookieDomain, +} from "../../core/session.ts"; +import { isSafeRedirectUrl } from "../../core/forward_auth.ts"; import { auditWrapper } from "../../core/audit.ts"; import { @@ -31,7 +36,15 @@ const origin = Deno.env.get("ORIGIN") || (import.meta.main ? undefined : "http://localhost"); // UI Route -loginRoutes.get("/login", (c) => { +loginRoutes.get("/login", async (c) => { + const auth = await getAuthenticatedUser(c); + if (auth) { + const redirectParam = c.req.query("redirect"); + if (redirectParam && isSafeRedirectUrl(redirectParam)) { + return c.redirect(redirectParam); + } + return c.redirect("/dashboard"); + } return c.html(LoginPageFragment()); }); diff --git a/src/features/auth/register_routes.ts b/src/features/auth/register_routes.ts index 75cf5ef..68d2fca 100644 --- a/src/features/auth/register_routes.ts +++ b/src/features/auth/register_routes.ts @@ -10,7 +10,7 @@ import type { RegistrationResponseJSON } from "jsr:@simplewebauthn/server@13"; import { valkey } from "../../core/valkey.ts"; import { getClientIp, publicRateLimiter } from "../../core/middleware.ts"; import { auditWrapper } from "../../core/audit.ts"; -import { getCookieDomain } from "../../core/session.ts"; +import { getAuthenticatedUser, getCookieDomain } from "../../core/session.ts"; import { createPasskey, @@ -30,7 +30,11 @@ const origin = Deno.env.get("ORIGIN") || (import.meta.main ? undefined : "http://localhost"); // UI Route -registerRoutes.get("/register", (c) => { +registerRoutes.get("/register", async (c) => { + const auth = await getAuthenticatedUser(c); + if (auth) { + return c.redirect("/dashboard"); + } const code = c.req.query("code") || ""; return c.html(RegisterPageFragment({ initialCode: code })); }); diff --git a/src/main.ts b/src/main.ts index d32d325..b3d0dfd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -32,8 +32,12 @@ app.use("*", contentNegotiation()); app.use("/public/*", serveStatic({ root: "./" })); // Root, Navigation & Logout Endpoints -app.get("/", (c) => { +app.get("/", async (c) => { c.header("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0"); + const auth = await getAuthenticatedUser(c); + if (auth) { + return c.redirect("/dashboard"); + } return c.redirect("/login"); });