design an auth solution that starts simple but could scale with the business, consider both security and user experiences, and talk about the future trends in this area
design an auth solution that starts simple but could scale with the business
consider both security and user experiences
talk about the future trends in this area
Big Picture: AuthN, AuthZ, and Identity Management
First-things-first, let's get back to basics
Authentication: figure out who you are
Authorization: figure out what you can do
In the beginning... Let there be a simple service...
Layered Architecture
Client stores a cookie or token as the proof of login status. (valet key
pattern)
Server persists a corresponding session
Token is usually in the format of JWT, signed by keys fetched from
somewhere secure (environment variables, AWS KMS, HashiCorp Vault,
etc.)
Popular web frameworks often prepare out-of-box auth solutions
Then, as the business grows, we scale the system with AKF scale cube:
X-axis: Horizontal clone
Y-axis: Functional decomposition
Z-axis: Sharding
Plus Conway's law: organization designs the systems mirroring its communication structure. We usually evolve the architecture to micro-services (see why microservices? for more)
Btw, "microservices vs. monolith" and "multi-repo vs. mono-repo" are different things.
For the enterprise, there are employee auth and customer auth. We focus more on the customer auth.
In the microservice world, let's take a functional slice of the authn and authz services, and there is an Identity and Access Management (IAM) team working on it.
Identity-aware proxy is a reverse proxy that allows either public endpoints or checks credentials for protected endpoints. If the credential is not presented but required, redirect the user to an identity provider. e.g. k8s ingress controller, nginx, envoy, Pomerium, ory.sh/oathkeeper, etc.
Identity provider and manager manages user identity through workflows like sign in, forgot password, MFA enrollment, etc. e.g. ory.sh/kratos, keycloak
OAuth2 and OpenID Connect provider issues tokens for first-party login (OIDC) and enables third-party developers to integrate via OAuth2. In practice this is often co-located with the identity provider — Keycloak, Auth0, and Okta all combine both — but can be separated: e.g., Ory Kratos for identity + Ory Hydra for OAuth2/OIDC.
The simplest solution is to submit the user's proof of identity and issue service credentials.
Argon2id (OWASP's current top recommendation), bcrypt, or scrypt for password hashing
However, modern apps often deal with complex workflows like conditional sign up, multi-step login, forgot password, etc.
Those workflows are essentially state transition graphs in the state machine.
And then finally get the access token and refresh token
access token is short-lived, and hence the attacking window is short if it is compromised
refresh token is single-use and rotated on each use; confidential clients (server-side) pair it with a client secret, while public clients (SPA, mobile) rely on rotating refresh tokens — store in an httpOnly cookie, never in localStorage
Revocation at the edge. A JWT is stateless and stays valid until it expires, but logout-all, a leaked token, or a banned user must take effect before expiry. So the identity-aware proxy checks a revocation list on every protected request. The authoritative store is a Redis token blocklist keyed by jti / session id / user id, with each entry's TTL set to the token's remaining lifetime so it self-cleans. To avoid a Redis round-trip on the overwhelming majority of requests (which are not revoked), an in-process Bloom filter sits in front: it answers "definitely not revoked" with zero network cost, and only on a possible hit (Bloom filters have false positives but never false negatives — so a revoked token is never wrongly allowed) does the proxy fall through to Redis to confirm. Standard Bloom filters can't delete, so rebuild it periodically from Redis (the entries expire with token TTL anyway), or use a counting/cuckoo variant. Short-lived access tokens (5–15 min) shrink the revocation window and reduce reliance on this path; if Redis is unreachable, auth typically fails closed.
The assumption is that there are so many entities involved in this workflow - client, resource owner, authorization server, resource server, network, etc. More entities introduce more exposure to attack. A comprehensive protocol should consider all kinds of edge cases. For example, what if the network is not HTTPs / cannot be fully trusted?
OpenID Connect is the identity protocol built on OAuth2, adding a signed ID token (JWT) that carries user identity claims, enabling Single Sign-On (SSO) across services.
SAML 2.0 is the older XML-based federation standard, still dominant for enterprise/B2B SSO (corporate IdPs like ADFS, Okta, Azure AD). New consumer apps default to OIDC; you typically need SAML support to sell into enterprises. Many providers (Okta, Keycloak, WorkOS) bridge both so the application sees a uniform identity regardless of the upstream protocol.
There are a lot of tricky details in those workflows and token handling processes. Don't reinvent the wheel.
In microservices, services also need to authenticate with each other — this is distinct from user-facing auth and is often overlooked:
mTLS (mutual TLS) — both sides present certificates; the service mesh (Istio, Linkerd) handles this transparently via sidecars. Identity is bound to the workload, not a human user.
SPIFFE/SPIRE — a standard for workload identity. Each service gets a cryptographic SVID (SPIFFE Verifiable Identity Document), usable with mTLS or JWT-SVIDs.
JWT propagation — the original user JWT is forwarded downstream, or the gateway mints a new service-scoped token. Each downstream service can then authorize the request without re-validating user credentials.
Don't roll your own token validation in every service — use a shared library or a sidecar.
Users tend to reuse the same username and password across multiple sites. When one of those sites suffers from a data breach, hackers brute-force attack other sites with those leaked credentials.
Passkeys (WebAuthn/FIDO2) — the current standard for phishing-resistant passwordless auth. Supported natively by all major platforms (Apple, Google, Microsoft) and browsers. The credential is a private key bound to the device and origin domain, making phishing structurally impossible. Preferred for all new implementations.
Synced passkeys (iCloud Keychain, Google Password Manager) enable cross-device use
Hardware security keys (YubiKey) for high-assurance scenarios
Biometric: Fingerprints, facial ID — typically implemented via platform authenticators that use WebAuthn under the hood. Trade-offs still apply.
Push Notification — used by apps like Duo, Okta Verify
How could clients subscribe to the server's state? Short polling, long polling, web socket, or server-sent events.
Managed solutions: Auth0, Okta, Amazon Cognito, Firebase Authentication, Clerk, WorkOS, Stytch. Clerk and WorkOS have become the go-to choices for new startups — Clerk for developer experience and Workos for B2B/enterprise SSO features; Auth0/Okta remain strong for large enterprise compliance requirements.
When the backend system gets too large, a user creation may fan out to many services and create a lot of entries in different data sources. It feels bad to wait for 15 seconds at the end of sign up, right?
Pioneered by the Google Zanzibar paper, this model expresses permissions as a graph of relationships between users and objects — e.g., "alice is an editor of document:X, which is in folder:Y that alice's team has viewer access to." Permissions compose recursively through the graph, enabling fine-grained checks that scale to billions of objects.
Western culture has a tradition to respect privacy, especially after the Nazis murdered millions of people.
Here are some typical sensitive data types: Personally Identifiable Information (PII), Protected Health Information (PHI, regulated by HIPAA), and Credit Card or Payment Card Industry (PCI) Information.