Skip to content

Frontend auth flow is non-functional: refresh route and login page do not exist in the live router #516

Description

@Xhristin3

Problem

The frontend authentication flow cannot complete. Three layers fail independently:

  1. AuthProvider calls a route handler that does not exist in the live router. app/components/auth-provider.tsx boots with fetch('/api/auth/refresh', { method: 'POST' }). The only route handler under the live src/app router is app/src/app/api/health/route.ts — there is no /api/auth/refresh there. The refresh call 404s, setState('unauthenticated') runs, and the user is redirected.

  2. The middleware redirects to a page that does not exist. app/src/middleware.ts sends unauthenticated /dashboard/* visitors to /auth/login. The login page exists at app/auth/login/page.tsx — outside the compiled router (see the app-router resolution issue, this issue's dependency) — so /auth/login is a 404 page.

  3. The auth route handlers that do exist are dead code and hardcode a local URL. app/api/auth/login/route.ts, app/api/auth/refresh/route.ts, and app/api/auth/logout/route.ts live at the project root, outside the router, and all three call http://localhost:3001/... directly. In any deployment where the API is not on the developer's localhost they cannot work, even if they were reachable.

Consequence: a fresh visitor to the app is bounced between a nonexistent refresh endpoint and a nonexistent login page. Registration (app/auth/register/page.tsx) exists as a page but its form posts to the same dead route layer. The product cannot be used through the web UI at all.

Root cause

// app/components/auth-provider.tsx
const res = await fetch('/api/auth/refresh', { method: 'POST' })   // ← no such route in src/app

// app/src/middleware.ts
if (isDashboardRoute && !token) {
  return NextResponse.redirect(new URL('/auth/login', request.url))  // ← no such page
}

Why this is architecturally hard

  1. The auth route handlers are the bridge between the browser (httpOnly cookie) and the API (JWT). The current design proxies POST /auth/refresh from a Next route handler so the cookie never leaves the same-site context. Moving these handlers into the live router is the first step, but the proxy must also stop hardcoding http://localhost:3001 — the API base URL must come from configuration (NEXT_PUBLIC_API_URL is already read in app/lib/api/*.ts; the route handlers ignore it).
  2. The API's refresh contract is cookie-only (api/src/auth/auth.controller.ts reads req.cookies.refresh_token). The Next proxy exists precisely because of that. Fixing the flow on the app side cannot change the API contract, so the proxy must forward the cookie (it already tries to) and must do so from a reachable location.
  3. The login/register pages (app/auth/login/page.tsx, app/auth/register/page.tsx) live in the pre-src layout; their fate is decided by the layout consolidation. This issue should not re-architect the layout — it should land after the router resolution issue and move/rewire the auth pages and routes into whichever layout becomes canonical.

Downstream impact

Depends on the app-router resolution issue (the empty-app/app router fix): until a layout is canonical, no page or route handler in this issue's scope is reachable. Beyond that dependency this is repo-local; the API contract is unchanged.

Acceptance criteria

Flow

  • POST /api/auth/refresh exists as a reachable route handler and returns 200 with { user, accessToken } when a valid refresh cookie is present.
  • /auth/login and /auth/register render as pages (not 404) and submit through the reachable proxy routes.
  • An unauthenticated visitor to /dashboard/streams is redirected to a working login page and, after login, lands back on the dashboard with AuthProvider in the authenticated state.
  • On reload with a valid refresh cookie, AuthProvider restores the session without redirecting to login.

Config

  • No route handler in the app hardcodes http://localhost:3001; the API base URL is resolved from config (NEXT_PUBLIC_API_URL or equivalent) consistently with app/lib/api/streams.ts.

Tests

  • Component tests for AuthProvider (app/components/auth-provider.test.tsx) cover the 200 and 401/404 refresh paths.
  • A test covers the middleware redirect for an unauthenticated /dashboard/* request and pass-through for authenticated ones.

Documentation

  • The README "Local Setup" section's frontend instructions describe the actual reachable auth pages.

Out of scope

Attaching the access token to dashboard API calls (separate issue), token refresh UI/UX, and any change to the API's cookie-based refresh contract.

Getting started

Real files in scope: app/api/auth/login/route.ts, app/api/auth/refresh/route.ts, app/api/auth/logout/route.ts (move into the canonical router location), app/auth/login/page.tsx, app/auth/register/page.tsx, app/components/auth-provider.tsx, app/src/middleware.ts, app/src/app/api/health/route.ts (pattern for a live route handler).

Verify with:

cd app && npm run typecheck && npm test && npm run build

Good first files to read: app/components/auth-provider.tsx, app/src/middleware.ts, app/api/auth/refresh/route.ts.

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardThird CampaignCampaign: Third CampaignauthAuthentication and authorizationbugSomething isn't workingfrontendRelated to app/ Next.js frontend

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions