103 lines
2.2 KiB
TypeScript
103 lines
2.2 KiB
TypeScript
import { cookies } from "next/headers";
|
|
import { NextResponse } from "next/server";
|
|
|
|
const ACCESS_TOKEN_COOKIE = "access_token";
|
|
const DEFAULT_COOKIE_MAX_AGE_SECONDS = 60 * 60;
|
|
|
|
export function getHermesUrl() {
|
|
return process.env.HERMES_INTERNAL_URL?.replace(/\/$/, "") ?? null;
|
|
}
|
|
|
|
export async function getAccessToken() {
|
|
const cookieStore = await cookies();
|
|
return cookieStore.get(ACCESS_TOKEN_COOKIE)?.value;
|
|
}
|
|
|
|
function isSecureCookieEnabled() {
|
|
if (process.env.AUTH_COOKIE_SECURE) {
|
|
return process.env.AUTH_COOKIE_SECURE !== "false";
|
|
}
|
|
|
|
return process.env.NODE_ENV === "production";
|
|
}
|
|
|
|
function normalizeMaxAge(maxAge?: number) {
|
|
if (typeof maxAge !== "number" || !Number.isFinite(maxAge) || maxAge <= 0) {
|
|
return DEFAULT_COOKIE_MAX_AGE_SECONDS;
|
|
}
|
|
|
|
return Math.floor(maxAge);
|
|
}
|
|
|
|
export function setAuthCookie(response: NextResponse, token: string, maxAge: number) {
|
|
response.cookies.set({
|
|
name: ACCESS_TOKEN_COOKIE,
|
|
value: token,
|
|
httpOnly: true,
|
|
secure: isSecureCookieEnabled(),
|
|
sameSite: "lax",
|
|
path: "/",
|
|
maxAge: normalizeMaxAge(maxAge),
|
|
});
|
|
}
|
|
|
|
export function clearAuthCookie(response: NextResponse) {
|
|
response.cookies.set({
|
|
name: ACCESS_TOKEN_COOKIE,
|
|
value: "",
|
|
httpOnly: true,
|
|
secure: isSecureCookieEnabled(),
|
|
sameSite: "lax",
|
|
path: "/",
|
|
maxAge: 0,
|
|
});
|
|
}
|
|
|
|
export function unauthorizedResponse() {
|
|
return NextResponse.json(
|
|
{ detail: "Nicht authentifiziert" },
|
|
{ status: 401 },
|
|
);
|
|
}
|
|
|
|
export function upstreamUnavailableResponse() {
|
|
return NextResponse.json(
|
|
{ detail: "Hermes ist nicht erreichbar" },
|
|
{ status: 502 },
|
|
);
|
|
}
|
|
|
|
export function upstreamConfigurationErrorResponse() {
|
|
return NextResponse.json(
|
|
{ detail: "Hermes ist nicht konfiguriert" },
|
|
{ status: 500 },
|
|
);
|
|
}
|
|
|
|
export async function readJson(response: Response) {
|
|
const text = await response.text();
|
|
|
|
if (!text) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
return JSON.parse(text);
|
|
} catch {
|
|
return { detail: text };
|
|
}
|
|
}
|
|
|
|
export async function hermesJsonResponse(response: Response) {
|
|
if (response.status === 204) {
|
|
return new NextResponse(null, {
|
|
status: 204,
|
|
});
|
|
}
|
|
|
|
const body = await readJson(response);
|
|
|
|
return NextResponse.json(body, {
|
|
status: response.status,
|
|
});
|
|
}
|