Files
pedwfrontend/docs/administrative-authentication.md
T

6.3 KiB

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 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/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 representation JSON unlocking uses the dedicated POST /api/admin/editRepJson route. That endpoint independently validates the administrative session, requires a trusted same-origin request, and validates the requested container and blob path before removing repComplete. The former /api/file/editRepJson route is retired and no longer performs storage access.

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.