fix: proxy.ts redirete staendig zurueck zu /login, obwohl eingeloggt
Der voran gegangene Fix (proxy.ts nach src/ verschoben, damit Next.js sie ueberhaupt erkennt) hat eine zweite, bislang tote Stelle live geschaltet: eine Cookie-Pruefung auf "refreshToken", die zu /login umleitet, wenn das Cookie fehlt - fuer /settings, /apiaries, /colonies, /queens. Dieses Cookie wird vom BACKEND gesetzt (eigene Domain, apicorebackend.* statt apicore.*, Pfad /api/v1/auth) und ist dem Browser zufolge nie Teil einer Anfrage an das Frontend - proxy.ts lief auf der Frontend-Domain und konnte dieses Cookie strukturell nie sehen. Solange die Datei am falschen Ort lag und nie ausgefuehrt wurde, blieb das folgenlos; sobald sie lief, hat sie jeden Aufruf dieser Seiten serverseitig zurueck zu /login geschickt, unabhaengig vom tatsaechlichen Login-Status. Die Cookie-Pruefung komplett entfernt statt repariert: es gibt keinen Weg, ein cross-origin gesetztes Cookie hier sichtbar zu machen, ohne seinen Schutz (Pfad-Scoping) aufzuweichen. Die echte Session lebt ohnehin nur clientseitig (Access-Token im Speicher, Refresh-Cookie nur fuer Backend-Aufrufe) - src/app/(app)/layout.tsx prueft das bereits korrekt und leitet bei Bedarf weiter. proxy.ts setzt jetzt nur noch die Security-Header. Lokal verifiziert: /settings/users ohne jedes Cookie liefert jetzt 200 statt eines Redirects, CSP zeigt weiterhin den korrekten Laufzeit-API_URL. Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
1 parent
c95e1c4b18
commit
1e53758753
1 file changed
+17
-41
@@ -1,24 +1,21 @@
|
||||
import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
|
||||
const SESSION_COOKIE = "refreshToken";
|
||||
|
||||
// Paths that redirect to /login when there's no session - kept identical to
|
||||
// the set this file already covered before security headers moved in here.
|
||||
// Broadening this would silently change auth-redirect behaviour for pages
|
||||
// that currently rely on client-side auth checks instead (dashboard,
|
||||
// bottling, etc.) and must not now start doing it as a side effect of the
|
||||
// matcher below being widened for headers.
|
||||
const AUTH_REDIRECT_PATTERNS = [
|
||||
/^\/settings(\/.*)?$/,
|
||||
/^\/apiaries(\/.*)?$/,
|
||||
/^\/colonies(\/.*)?$/,
|
||||
/^\/queens(\/.*)?$/,
|
||||
];
|
||||
|
||||
function needsAuthRedirectCheck(pathname: string): boolean {
|
||||
return AUTH_REDIRECT_PATTERNS.some((pattern) => pattern.test(pathname));
|
||||
}
|
||||
// There used to be a cookie-based redirect-to-/login check here, gated on
|
||||
// the "refreshToken" cookie. It could never work: that cookie is set by the
|
||||
// BACKEND's own origin (a different domain, apicorebackend.* vs apicore.*),
|
||||
// scoped to /api/v1/auth - the browser never sends it on requests to the
|
||||
// frontend, so this proxy (running on the frontend's origin) can never see
|
||||
// it. The check always evaluated "no session", harmless while this file
|
||||
// sat in the wrong directory and never ran at all, but once relocated so
|
||||
// Next.js actually picked it up, it started force-redirecting every visit
|
||||
// to /settings, /apiaries, /colonies, /queens straight back to /login,
|
||||
// regardless of whether the user was genuinely logged in - login state for
|
||||
// this app is only observable client-side (in-memory access token,
|
||||
// cross-origin refresh cookie), which is exactly what
|
||||
// src/app/(app)/layout.tsx already correctly redirects on. Removed rather
|
||||
// than patched: there is no way to make a cross-origin cookie visible to
|
||||
// this server without weakening the cookie itself (e.g. dropping its path
|
||||
// scope), which isn't worth it for a redirect the client already handles.
|
||||
|
||||
// Deliberately computed here, not in next.config.ts: that file's headers()
|
||||
// is resolved once at build time and frozen into the standalone output, so
|
||||
@@ -64,32 +61,11 @@ function withSecurityHeaders(response: NextResponse): NextResponse {
|
||||
return response;
|
||||
}
|
||||
|
||||
export function proxy(request: NextRequest) {
|
||||
const hasSession = request.cookies.has(SESSION_COOKIE);
|
||||
const { pathname } = request.nextUrl;
|
||||
|
||||
if (pathname.startsWith("/login")) {
|
||||
if (hasSession) {
|
||||
return withSecurityHeaders(
|
||||
NextResponse.redirect(new URL("/settings/users", request.url)),
|
||||
);
|
||||
}
|
||||
return withSecurityHeaders(NextResponse.next());
|
||||
}
|
||||
|
||||
if (needsAuthRedirectCheck(pathname) && !hasSession) {
|
||||
return withSecurityHeaders(
|
||||
NextResponse.redirect(new URL("/login", request.url)),
|
||||
);
|
||||
}
|
||||
|
||||
export function proxy() {
|
||||
return withSecurityHeaders(NextResponse.next());
|
||||
}
|
||||
|
||||
export const config = {
|
||||
// Broadened from the original 5-path list so every page gets the security
|
||||
// headers (not just the ones that also happen to need the auth-redirect
|
||||
// check, which is now handled separately above, unchanged in scope).
|
||||
matcher: [
|
||||
"/((?!_next/static|_next/image|favicon.ico|sw.js|manifest.webmanifest|icon.svg).*)",
|
||||
],
|
||||
|
||||
Reference in new issue
Block a user