76 lines
2.5 KiB
TypeScript
76 lines
2.5 KiB
TypeScript
/**
|
|
* Edge-safe Neon Auth configuration.
|
|
*
|
|
* This file is imported by `src/middleware.ts`, which runs in the Edge
|
|
* runtime. It must NOT import:
|
|
* - `pg` / any Node-only database driver
|
|
* - The Drizzle client
|
|
* - Anything else that touches the Node.js runtime
|
|
*
|
|
* Both the middleware and the server-side handler in `src/lib/auth.ts`
|
|
* share the same session cookie, so the middleware can read sessions
|
|
* minted by the server-side handler.
|
|
*
|
|
* Environment variables required:
|
|
* NEON_AUTH_BASE_URL — from `neonctl neon-auth status` (Auth Base URL)
|
|
* NEON_AUTH_COOKIE_SECRET — min 32-char secret: openssl rand -base64 32
|
|
*/
|
|
|
|
export interface NeonAuthBaseConfig {
|
|
baseUrl: string;
|
|
cookieSecret: string;
|
|
}
|
|
|
|
/**
|
|
* Returns the Neon Auth base config for server-side use.
|
|
* Called by both the edge middleware and the Node-only auth lib.
|
|
*/
|
|
export function getNeonAuthConfig(): NeonAuthBaseConfig {
|
|
const baseUrl = process.env.NEON_AUTH_BASE_URL || "";
|
|
const cookieSecret = process.env.NEON_AUTH_COOKIE_SECRET || "";
|
|
|
|
// Detect CI build context: DATABASE_URL is set (Build step), but one or both Neon Auth
|
|
// vars are empty. Return a placeholder so `next build` succeeds — auth is validated
|
|
// at runtime when actually needed.
|
|
const isCIBuild = !!process.env.DATABASE_URL && (!baseUrl || !cookieSecret);
|
|
|
|
if (!baseUrl || baseUrl === "placeholder") {
|
|
if (isCIBuild) {
|
|
return { baseUrl: "https://placeholder.local", cookieSecret: "dev-cookie-secret-placeholder-32chars!!" };
|
|
}
|
|
throw new Error(
|
|
"NEON_AUTH_BASE_URL is not set. Run `neonctl neon-auth status` to get the value."
|
|
);
|
|
}
|
|
|
|
if (!cookieSecret) {
|
|
if (isCIBuild) {
|
|
return { baseUrl, cookieSecret: "dev-cookie-secret-placeholder-32chars!!" };
|
|
}
|
|
throw new Error(
|
|
"NEON_AUTH_COOKIE_SECRET is not set. Generate one: openssl rand -base64 32"
|
|
);
|
|
}
|
|
|
|
if (cookieSecret.length < 32) {
|
|
throw new Error("NEON_AUTH_COOKIE_SECRET must be at least 32 characters.");
|
|
}
|
|
|
|
return { baseUrl, cookieSecret };
|
|
}
|
|
|
|
/**
|
|
* Returns the Neon Auth base config, or null if not configured.
|
|
* Use this for middleware that should gracefully degrade if auth is not set up.
|
|
*/
|
|
export function getNeonAuthConfigOptional(): NeonAuthBaseConfig | null {
|
|
const baseUrl = process.env.NEON_AUTH_BASE_URL || "";
|
|
const cookieSecret = process.env.NEON_AUTH_COOKIE_SECRET || "";
|
|
|
|
if (!baseUrl || !cookieSecret || cookieSecret.length < 32) {
|
|
return null;
|
|
}
|
|
|
|
return { baseUrl, cookieSecret };
|
|
}
|