# Administrative authentication foundation ## Integrated administrative sign-in Administrators sign in at `/admin/login` using the shared credential configured as `ADMIN_AUTH_SECRET`. The page submits the credential directly to `POST /api/admin/auth/login`; it does not place the credential in a URL or store it in browser storage. Successful authentication creates the administrative session cookie and sends the browser to `/admin`. The `/admin` server-side loader validates that cookie before loading administrative data. A valid session is not sufficient by itself: the existing `/admin` IP allowlist remains an additional restriction, and a valid administrator outside the allowed network is sent to `/403`. The administrative interface provides a **Sign out** control which calls `POST /api/admin/auth/logout`, clears the cookie, and returns the browser to `/admin/login`. Sessions expire after 20 minutes and expired, invalid, or missing sessions are redirected to the login page. ## Required server-side configuration The deployment must provide all of the following server-side values: - `ADMIN_AUTH_SECRET`: a unique high-entropy administrative passphrase of at least 32 characters. - `ADMIN_SESSION_SECRET`: a different unique high-entropy signing key of at least 32 characters. - `NEXTAUTH_URL`: the existing canonical application URL. Administrative login and logout compare the request `Origin` with this server-configured origin. The administrative values must never use a `NEXT_PUBLIC_` prefix or be exposed to browser JavaScript. Do not commit real values. Missing, short, or identical administrative secrets fail closed. ## Security properties and limitations - Credentials are derived with Node `scrypt` and compared with `timingSafeEqual`. - Sessions are stateless, versioned HMAC-SHA256 tokens with a 20-minute fixed lifetime and a random nonce. - The cookie is `HttpOnly`, `SameSite=Strict`, scoped to `/`, explicitly expires, and is `Secure` in production. - Login and logout require an exact same-origin `Origin` match against `NEXTAUTH_URL`; missing or malformed origins fail closed. - Authentication responses use `Cache-Control: no-store`. - Logout clears the browser cookie. Because sessions are stateless, a stolen token can remain valid until its short expiry; later protected routes must continue verifying signature and expiry on every request. - This is shared-credential authentication. A valid token proves knowledge of the shared credential, not the identity of a named administrator. - Protecting `/admin` prevents its server-side Prisma, storage, and CRM data loading from running without a valid administrative session. It does not by itself protect browser-addressable API routes. ## Administrative API protection limitations The current administrative UI directly uses API routes that do not yet enforce the administrative session, including: - `/api/admin/getnewappeals_api` - `/api/admin/getlatestdocuments_api` - `/api/admin/getStatusCountsByAppeal_api` - `/api/admin/getStatusCountsByAppealAndLPA_api` The appeals and documents routes expose paging operations used after the page has loaded. The status routes expose administrative dashboard reads. These routes retain their existing relay token and HMAC behaviour but have no independent administrative-session authorization. A later authorised stage must enforce the administrative session on privileged API routes and account for both browser calls and the existing server-side bootstrap callers. Storage download, representation editing, and queue actions retain their existing authorization behaviour. The other administrative API and storage limitations described in this section remain open. Directly observed storage routes include: - `/api/file/getrepsblobproxy`, which forwards a caller-supplied container using server relay credentials and path signing. - `/api/file/editRepJson`, which performs a direct blob mutation and has no visible administrative-session or HMAC check. - `/api/file/downloadblob` and `/api/file/createrepcompletemessage_api`, which enforce existing path-HMAC checks but not administrative authorization. ## Stage 3 deletion controls Ordinary case and representation deletion through `/api/file/deleteblobcase` and `/api/file/deleteblobrep` now requires a valid NextAuth session whose user ID matches the requested Azure container. The existing signed-query/HMAC check also remains required. Requests that fail ownership or HMAC validation are rejected before the Azure storage deletion operation is called. Administrative cross-container representation deletion uses the dedicated `POST /api/admin/deleteblobrep` route. That endpoint independently validates the administrative session and requires a trusted same-origin request. It also validates the requested container, case-folder segment, and representation-file segment before performing deletion. Administrative case deletion was not investigated or remediated as part of Stage 3 and remains a separate, unverified security boundary. The other administrative API and storage limitations documented above also remain open. Automated contract verification for the implemented deletion controls has passed. Live Azure behaviour, browser-level behaviour, and deployment configuration have not been verified by that automated coverage. These changes do not establish closure of the overall ITHC finding. ## Deployment requirements before production use The repository does not provide a demonstrated distributed rate-limit service. Administrative login must therefore be protected by an ingress, gateway, WAF, or shared backing service that enforces rate limits consistently across all deployed instances. A process-local limiter is intentionally not used because it would reset on restart and could be bypassed across instances. The deployment must also ensure `NEXTAUTH_URL` is the correct canonical HTTPS origin. Login and logout intentionally do not derive trust from `Host` or forwarding headers. Any future administrative state-changing API must require more than possession of the cookie: it must independently validate the administrative session and enforce same-origin/CSRF protection before performing side effects.