Authentication & the request model
Every request to the platform passes through one gateway. The gateway is the only place a JWT is ever parsed — it validates the token once, then signs and injects a set of identity headers into the request before forwarding it to whichever service handles it.
POST /api/v1/orders HTTP/1.1 Host: api.mergemind.co Authorization: Bearer <jwt> ↓ Gateway validates the JWT once ↓ X-User-Id: 7c1e... X-Tenant-Id: 3af0... X-User-Roles: TENANT_ADMIN X-User-Permissions: COMMERCE_WRITE,COMMERCE_READ,... X-Gateway-Signature: 8f2a... X-Gateway-Timestamp: 1758012345 ↓ forwarded to the service ↓ Service verifies the HMAC signature against the timestamp + headers. It never sees the original JWT and never parses a token itself.
Downstream services verify the X-Gateway-Signature (an HMAC over the headers and timestamp) rather than re-validating the JWT. That means authentication logic exists in exactly one place in the whole platform — not duplicated, and not subtly different, across sixteen services.
Multi-factor authentication
TOTP-based MFA with backup codes is built in, alongside SSO and invite-based user provisioning. A tenant can require MFA for all members via a per-tenant policy.
Token security
Refresh tokens are one-time use — each refresh mints a new one and invalidates the old, so a stolen refresh token is only useful once. Individual tokens can be blacklisted by JTI, and a tenant admin can revoke every active session for a user in one call (useful for an offboarding flow, or responding to a suspected compromise).
Why this design: a common failure mode in hand-rolled multi-service auth is each service parsing and trusting a JWT slightly differently — one checks expiry and nothing else, another trusts a claim it shouldn't. Centralising verification at the gateway and passing a signed, already-verified context downstream removes that entire class of bug.