Give /api/preview-link its own Bearer secret; constant-time token checks
preview-link mints working form links for any contact, but was gated by HEALTH_TOKEN (the diagnostics secret) passed in the query string, where it lands in access logs. README already documented PREVIEW_ADMIN_TOKEN as a Bearer header; make the code match. - PREVIEW_ADMIN_TOKEN, when set, is required as Authorization: Bearer and is never accepted from the URL. - Until it is set, HEALTH_TOKEN still works (Bearer or legacy ?token=) so the support runbook in EMAIL_DELIVERY.md keeps working. - preview-link and /api/health compare tokens in constant time. - redact() also scrubs PREVIEW_ADMIN_TOKEN and STAFF_REPORT_KEY.
This commit is contained in:
+14
-1
@@ -22,6 +22,11 @@ export interface AppEnv {
|
||||
* string and pass via `?token=<>` to the health endpoint to read diagnostics.
|
||||
*/
|
||||
healthToken?: string;
|
||||
/**
|
||||
* Dedicated secret for /api/preview-link, sent as `Authorization: Bearer`.
|
||||
* When unset, that endpoint falls back to HEALTH_TOKEN.
|
||||
*/
|
||||
previewAdminToken?: string;
|
||||
/**
|
||||
* Same-origin host this app runs at. Used to build `frame-ancestors 'self'`
|
||||
* and any absolute self-links. Defaults to inferring from the request.
|
||||
@@ -46,6 +51,7 @@ export function appEnv(): AppEnv {
|
||||
basicAuthUser: process.env.CIVI_HTTP_AUTH_USER,
|
||||
basicAuthPass: process.env.CIVI_HTTP_AUTH_PASS,
|
||||
healthToken: process.env.HEALTH_TOKEN,
|
||||
previewAdminToken: process.env.PREVIEW_ADMIN_TOKEN,
|
||||
publicOrigin: process.env.PUBLIC_ORIGIN,
|
||||
};
|
||||
// In production, refuse to start in stub mode — that's almost certainly a
|
||||
@@ -64,7 +70,14 @@ export function appEnv(): AppEnv {
|
||||
export function redact(s: string): string {
|
||||
let out = s;
|
||||
const e = appEnv();
|
||||
for (const v of [e.civiApiKey, e.civiSiteKey, e.basicAuthPass, e.healthToken]) {
|
||||
for (const v of [
|
||||
e.civiApiKey,
|
||||
e.civiSiteKey,
|
||||
e.basicAuthPass,
|
||||
e.healthToken,
|
||||
e.previewAdminToken,
|
||||
process.env.STAFF_REPORT_KEY,
|
||||
]) {
|
||||
if (v && v.length >= 6) out = out.split(v).join("«redacted»");
|
||||
}
|
||||
return out;
|
||||
|
||||
Reference in New Issue
Block a user