diff --git a/.env.example b/.env.example index 2776f80629..719a185f20 100644 --- a/.env.example +++ b/.env.example @@ -225,4 +225,21 @@ HINDSIGHT_API_LOG_LEVEL=info # Optional: Require a shared access key to view the Control Plane UI. # When set, visitors see a login page and must enter the key before # accessing the dashboard or any /api/* routes (except /api/health). +# This key is the admin scope: it sees every bank (prefix ""). # HINDSIGHT_CP_ACCESS_KEY=your-shared-secret-key + +# Optional: Additional scoped tokens, each mapped to a bank-id prefix, so the +# Control Plane can be embedded per-user. JSON array of {token, prefix, label?}. +# A scoped token only sees banks equal to its prefix or namespaced under it +# ("u2" matches "u2" and "u2--*", never "u20"). The admin key above stays all-banks. +# HINDSIGHT_CP_TOKENS=[{"token":"user-2-token","prefix":"u2","label":"user 2"}] + +# Optional: SameSite policy for the CP session cookie. Set to "none" so the +# cookie survives inside a cross-site iframe (adds Secure + Partitioned/CHIPS; +# requires HTTPS). Leave unset for local http dev to keep SameSite=Lax. +# HINDSIGHT_CP_COOKIE_SAMESITE=none + +# Optional: Origins allowed to embed the Control Plane in an iframe +# (Content-Security-Policy: frame-ancestors). Space- or comma-separated list, +# e.g. the tokengate origin. Falls back to 'self' when unset. +# HINDSIGHT_CP_FRAME_ANCESTORS=https://tokengate.example.com diff --git a/hindsight-control-plane/src/app/api/auth/embed-login/route.ts b/hindsight-control-plane/src/app/api/auth/embed-login/route.ts new file mode 100644 index 0000000000..0d59b8f724 --- /dev/null +++ b/hindsight-control-plane/src/app/api/auth/embed-login/route.ts @@ -0,0 +1,102 @@ +import { NextRequest, NextResponse } from "next/server"; +import { localizeApiErrorPayload } from "@/lib/i18n/api-errors"; + +import { + ACCESS_KEY_COOKIE, + SESSION_MAX_AGE_SECONDS, + createSessionToken, + sessionCookieOptions, +} from "@/lib/auth/session"; +import { resolveToken } from "@/lib/auth/tokens"; +import { sanitizeReturnTo, withBasePath } from "@/lib/base-path"; + +const DEFAULT_RETURN_TO = "/dashboard"; + +/** + * Cross-site auto-login for the tokengate iframe. A hidden `