fix: proxy.ts redirete staendig zurueck zu /login, obwohl eingeloggt
Backend Image / build-and-push (push) Successful in 2m19s
Frontend Image / build-and-push (push) Successful in 2m2s

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:
Nick SzaunigandClaude Sonnet 5 committed 2026-09-03 01:20:51 +02:00
1 parent c95e1c4b18
commit 1e53758753
1 file changed
+17 -41
+17 -41
View File
@@ -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).*)",
],