Case Study 01
Designing a Zero-Trust Authentication Platform
The problem
The estate had grown as a set of independently built portals, each with its own login and user store. A user needed a different credential for every application, administrators had no single place to grant or revoke access, and there was no consistent way for one service to trust a request from another. The goal was a single identity for every user and no implicit trust anywhere — between a browser and a service, or between two services.
Design constraints
- One sign-in usable across many applications on shared subdomains.
- Short-lived, app-scoped access so a leaked token has minimal blast radius.
- Authorization scoped to an organisational hierarchy (a user’s powers differ by office and by application).
- Every service-to-service call authenticated and replay-proof, without a shared network being treated as “trusted”.
Architecture
Responsibilities were deliberately split into two services. A user-facing SSO portal authenticates the person (password + TOTP, or federated Google within the organisation domain) but never mints tokens. A headless token authority owns the entire token lifecycle and is called service-to-service.
Token design
- Access tokens — RS256, ~15 minutes, audience-scoped to a single application, held in browser memory only (never persisted) and refreshed transparently.
- Refresh tokens — RS512, HttpOnly / Secure / SameSite cookie scoped to the shared parent domain; only a hash of the token is stored server-side.
- Rotation with reuse detection — every refresh re-issues the token and atomically invalidates the previous hash. A valid-but-superseded token appearing again is treated as a stolen-token replay and revokes every session for that user.
- Sliding idle window & context binding — a Redis-backed idle timeout plus a per-request context hash (user, app, device, role, office) that must match, giving instant revocation the moment any of it changes.
- Device binding — a signed device identity cookie; device identity is read only from the signed cookie, never from client-supplied headers.
Custom RBAC — a role × office × application model
Off-the-shelf role systems assume flat, global roles. The organisation is a deep hierarchy (zone → circle → division → sub-division), and the same role means different things in different offices and applications. Authorization is therefore modelled as a triple — { role, office, application } — attached to a user. Offices form a self-referential tree; roles carry granular boolean permissions and a delegation graph describing which roles may grant which. Role changes and office re-parenting are transactional and fully audited (with time-expiring audit logs).
Zero-trust service mesh
No service trusts another because they share a cluster. Every internal call is signed with HMAC-SHA256 over a canonicalised payload and timestamp, verified with a constant-time comparison inside a 5-minute replay window, and attributed to a named caller. Downstream services verify access tokens locally (signature + Redis context check) rather than round-tripping to the auth service on every request — so the auth service is on the path only for refresh and issuance.
The security controls — signing, verification, rate limiting, headers, device identity — live in a shared library, so every current and future service inherits the same hardened defaults rather than re-implementing them.
Outcome
A user now signs in once and moves across ~20 applications with a single governed identity; administrators grant and revoke access from one place; and no request — from a browser or another service — is trusted without cryptographic proof. An OIDC provider (authorization-code + PKCE) extends the same identity to third-party tools such as the monitoring stack.