git-subtree-dir: apps/web git-subtree-mainline:068a51b46bgit-subtree-split:1e7174fa60
89 lines
2.5 KiB
TypeScript
89 lines
2.5 KiB
TypeScript
import { headers as nextHeaders } from "next/headers";
|
|
import { auth } from "~/lib/auth";
|
|
|
|
const MOBILE_AUTH_COOKIE_HEADER = "x-beenvoice-auth-cookie";
|
|
const MOBILE_SESSION_TOKEN_HEADER = "x-beenvoice-session-token";
|
|
const MAX_AUTH_COOKIE_HEADER_LENGTH = 16 * 1024;
|
|
const MAX_SESSION_TOKEN_LENGTH = 255;
|
|
const SESSION_TOKEN_PATTERN = /^[A-Za-z0-9._~+/=-]+$/;
|
|
|
|
function looksLikeSessionCookie(cookie: string): boolean {
|
|
return cookie.split(";").some((part) => {
|
|
const name =
|
|
part
|
|
.trim()
|
|
.split("=", 1)[0]
|
|
?.replace(/^__Secure-/, "") ?? "";
|
|
return (
|
|
name === "better-auth.session_token" ||
|
|
name === "better-auth.session_data" ||
|
|
name.startsWith("better-auth.session_token.") ||
|
|
name.startsWith("better-auth.session_data.") ||
|
|
name.endsWith(".session_token") ||
|
|
name.endsWith(".session_data") ||
|
|
name.includes(".session_token.") ||
|
|
name.includes(".session_data.")
|
|
);
|
|
});
|
|
}
|
|
|
|
export function headersWithAuthCookieFallback(headers: Headers): Headers {
|
|
const mobileCookie = headers.get(MOBILE_AUTH_COOKIE_HEADER)?.trim();
|
|
if (
|
|
mobileCookie &&
|
|
mobileCookie.length <= MAX_AUTH_COOKIE_HEADER_LENGTH &&
|
|
looksLikeSessionCookie(mobileCookie)
|
|
) {
|
|
const nextHeaders = new Headers(headers);
|
|
nextHeaders.set("cookie", mobileCookie);
|
|
return nextHeaders;
|
|
}
|
|
|
|
if (headers.get("cookie")?.trim()) return headers;
|
|
|
|
const sessionToken = headers.get(MOBILE_SESSION_TOKEN_HEADER)?.trim();
|
|
if (
|
|
sessionToken &&
|
|
sessionToken.length <= MAX_SESSION_TOKEN_LENGTH &&
|
|
SESSION_TOKEN_PATTERN.test(sessionToken)
|
|
) {
|
|
const nextHeaders = new Headers(headers);
|
|
nextHeaders.set(
|
|
"cookie",
|
|
[
|
|
`better-auth.session_token=${sessionToken}`,
|
|
`__Secure-better-auth.session_token=${sessionToken}`,
|
|
].join("; "),
|
|
);
|
|
return nextHeaders;
|
|
}
|
|
|
|
return headers;
|
|
}
|
|
|
|
export function hasSessionCookie(headers: Headers): boolean {
|
|
const cookie = headers.get("cookie") ?? "";
|
|
if (!cookie.trim()) return false;
|
|
|
|
return looksLikeSessionCookie(cookie);
|
|
}
|
|
|
|
export async function getOptionalServerSession(headers: Headers) {
|
|
headers = headersWithAuthCookieFallback(headers);
|
|
|
|
if (!hasSessionCookie(headers)) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
return await auth.api.getSession({ headers });
|
|
} catch (error) {
|
|
console.error("[auth] Failed to resolve session:", error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export async function getOptionalServerSessionFromHeaders() {
|
|
return getOptionalServerSession(await nextHeaders());
|
|
}
|