security(auth): move guest credentials to secure server-side API route and update docker config
All checks were successful
Deploy Flowstate to VPS / deploy (push) Successful in 48s

This commit is contained in:
Chneemann 2026-08-23 11:46:07 +02:00
parent f99d1f15c4
commit 9ae5ddaf90
No known key found for this signature in database
4 changed files with 82 additions and 13 deletions

View file

@ -10,13 +10,6 @@ WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules COPY --from=deps /app/node_modules ./node_modules
COPY . . COPY . .
# Inject NEXT_PUBLIC_ vars at build time (required for client-side embedding)
ARG NEXT_PUBLIC_GUEST_EMAIL
ARG NEXT_PUBLIC_GUEST_PASSWORD
ENV NEXT_PUBLIC_GUEST_EMAIL=$NEXT_PUBLIC_GUEST_EMAIL
ENV NEXT_PUBLIC_GUEST_PASSWORD=$NEXT_PUBLIC_GUEST_PASSWORD
RUN npm run build RUN npm run build
# 3. Run production image (Node.js server) # 3. Run production image (Node.js server)

View file

@ -8,7 +8,7 @@
import { useState } from "react"; import { useState } from "react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import Link from "next/link"; import Link from "next/link";
import { getGuestCredentials, loginUser } from "@/services/auth.service"; import { loginAsGuest, loginUser } from "@/services/auth.service";
/** /**
* Renders the login page containing the authentication form, error handling, * Renders the login page containing the authentication form, error handling,
@ -65,7 +65,7 @@ export default function LoginPage() {
}; };
/** /**
* Fetches guest user credentials and triggers guest authentication. * Triggers secure guest authentication via the backend service.
* *
* @async * @async
*/ */
@ -73,15 +73,15 @@ export default function LoginPage() {
setError(null); setError(null);
setLoadingType("guest"); setLoadingType("guest");
const result = await getGuestCredentials(); const result = await loginAsGuest();
if (result.error || !result.email || !result.password) { if (result.error) {
setError(result.error || "Guest login is not configured properly."); setError(result.error);
setLoadingType(null); setLoadingType(null);
return; return;
} }
await handleSignIn(result.email, result.password, "guest"); router.push("/summary");
}; };
return ( return (

View file

@ -0,0 +1,51 @@
/**
* @file api/auth/guest/route.ts
* @description API route handler for guest authentication utilizing server-side environment variables and auto sign-in.
*/
import { NextResponse } from "next/server";
import { signIn } from "@/auth";
/**
* Handles POST requests to authenticate as a guest user using environment credentials.
*
* @async
* @returns {Promise<NextResponse>} A JSON response confirming successful guest sign-in or an error message.
*/
export async function POST() {
const email = process.env.GUEST_EMAIL;
const password = process.env.GUEST_PASSWORD;
if (!email || !password) {
return NextResponse.json(
{ error: "Guest login is not configured on the server." },
{ status: 500 },
);
}
try {
await signIn("credentials", {
email,
password,
redirect: false,
});
return NextResponse.json({ success: true }, { status: 200 });
} catch (error: any) {
console.error("Guest login error:", error);
if (
error?.message?.includes("CredentialsSignin") ||
error?.type === "CredentialsSignin"
) {
return NextResponse.json(
{ error: "Incorrect guest credentials." },
{ status: 401 },
);
}
return NextResponse.json(
{ error: "Internal Server Error" },
{ status: 500 },
);
}
}

View file

@ -23,6 +23,31 @@ export async function getGuestCredentials() {
return { email, password }; return { email, password };
} }
/**
* Triggers guest authentication securely via the backend API route.
*
* @async
* @returns {Promise<{ success?: boolean; error?: string }>} An object indicating success or describing the error.
*/
export async function loginAsGuest() {
try {
const response = await fetch("/api/auth/guest", {
method: "POST",
headers: { "Content-Type": "application/json" },
});
const data = await response.json();
if (!response.ok) {
return { error: data.error || "Guest login failed." };
}
return { success: true };
} catch (err: any) {
return { error: "Server error: API endpoint not available" };
}
}
/** /**
* Authenticates a user using email and password credentials, performing client-side validation first. * Authenticates a user using email and password credentials, performing client-side validation first.
* *