The authentication strategy decision record: why the session management approach you chose in year one determines your SSO migration cost and your compliance posture in year three
Authentication libraries are chosen from quickstart tutorials, copied from a colleague's starter kit, or selected by a founder who needed users to be able to log in by the end of the day. Two years later, the session management approach embedded in that first sprint determines whether adding SSO for your first enterprise customer takes two days or two months, whether a compromised token can be revoked before it expires, and whether your SOC 2 audit finds undocumented session data retention with no documented basis for the retention period. None of these consequences were legible when the decision was made. None of them are written down anywhere.
An engineering team is closing its first enterprise contract. The enterprise customer has one requirement before signing: their employees must be able to log in through Okta using SAML 2.0. The team's authentication is built on JWTs minted by the application itself — a standard implementation, correctly done, working fine in production for 18 months. The engineer assigned to add SAML support opens the authentication code for the first time since it was written.
The JWT payload contains 14 fields: user ID, email, role, organization ID, feature flags, subscription tier, onboarding state, last-seen timestamp, timezone, two experiment cohort assignments, a legacy field that appears to be unused but removing it breaks something undocumented, and a field called admin_override that was added by a contractor eight months ago. The JWT is verified in a middleware that runs on every request. The verified user object from the JWT is passed to application code in 200 places.
Adding SAML means the JWT can no longer be the authoritative source of truth for user identity. The IdP is the authoritative source. The IdP knows the user's email. It does not know the user's feature flags, subscription tier, or onboarding state — those live in the application database. The SAML assertion arrives, the user is authenticated, and now the application must merge the IdP identity with the application user record to reconstitute the 14-field JWT that every piece of application code expects. But users who log in via Okta have a different identifier than users who created accounts directly — the Okta subject is a stable opaque ID like 00u1a2b3c4d5e6f7g8h9, not an email address. The application's user table uses email as the primary join key in 11 foreign key relationships.
The SSO integration is not two days. It is six weeks, a user ID migration that requires a multi-hour maintenance window, a feature flag system rewrite to move flags out of the JWT and into a database table, and a decision to leave admin_override in the JWT as a short-term technical debt item that is still there two years later.
Like most foundational infrastructure decisions, the authentication strategy is visible as a working system but invisible as a set of decisions. The 14 fields in the JWT, the email-as-primary-key design, the decision to put feature flags in the token rather than fetch them from the database — each was made in a distinct context, with a specific reasoning that made sense at the time. The JWT field count grew from 3 to 14 over 18 months, one field at a time, each addition a small decision that felt like a trivial implementation detail. By the time the SSO requirement arrives, the authentication strategy is not a strategy — it is an accretion of small decisions with no center, no documentation, and no map.
Why authentication is an architectural decision, not a library choice
The perception that authentication is a solved problem — "just use NextAuth" or "just use Auth0" — obscures what is actually being decided when authentication is first implemented. The library or provider solves the protocol: the cryptographic operations, the CSRF protection, the redirect flows. The architectural decision is everything else: what constitutes user identity in this system, where session state lives, what claims are in the token and why, how roles and permissions are represented and enforced, what the compliance obligations are and how the implementation satisfies them.
The properties that make authentication an architectural decision rather than a library configuration:
Session management is a distributed state design choice. Every authenticated request requires answering the question: "is this user who they say they are, and what are they allowed to do?" The answer can come from a session store (stateful: the server holds the session data, the client holds only a session ID), from a self-contained token (stateless: the token contains all session data, verified cryptographically, no server state required), or from an identity provider (federated: an external authority asserts identity, the application trusts the assertion). These three approaches have different consistency properties, different revocation behaviors, different performance characteristics, and different migration paths. The choice made at project start shapes all three, with consequences that compound over time as application state is layered into the session.
The token design is a schema that cannot easily be changed once deployed. A JWT payload is not a database schema with a migration tool — there is no Flyway for JWT claims. Once application code reads a claim from a token, that claim must be present in every token issued, until the consuming code is updated and deployed to no longer read it. If that claim is read in 200 places across the codebase, removing it is a refactor that touches 200 files. If that claim was populated with stale data when the token was issued (because the JWT was valid for 7 days and the user's subscription changed on day 2), the application sees stale authorization data until the token expires. Like database migrations, token schema changes at scale are not reversible without careful forward-planning — but unlike database migrations, there is rarely a tool that enforces a migration policy or records the history of schema changes.
The security properties of the authentication design are not visible in the code. A JWT stored in localStorage is functionally identical to a JWT stored in an httpOnly cookie from the application's perspective — the authentication middleware verifies the token and populates the user object. The security difference is not in the application logic; it is in the attack surface exposed. localStorage is accessible to any JavaScript running in the page, including third-party scripts, meaning an XSS vulnerability anywhere in the application can read and exfiltrate the token. An httpOnly cookie is not accessible to JavaScript; an XSS vulnerability cannot read it. This difference is not documented in the code. It is a decision that was made at implementation time, implicitly or explicitly, and the security team discovers the current state at audit time by inspecting the response headers rather than by reading documentation. Security ADRs that document the threat model depend on the authentication strategy being documented — the two documents are the same system described at different layers of abstraction.
Authentication decisions accumulate without a record. The initial choice of session management model is rarely the last authentication decision. Feature flags move into the JWT "for performance." A second role type is added and squeezed into the existing role field with a pipe-delimited string. CSRF protection is added after a pen test finding. A refresh token rotation policy is introduced after a token exposure incident. Password reset tokens are issued with the same signing key as session tokens. Multi-tenancy isolation is enforced by an org_id check in the middleware that was added one afternoon and never formally reviewed. Each of these is a decision with security consequences, and each is made in isolation. The authentication strategy ADR is the document that holds the accumulation together — the record that makes the full system legible.
Session management approaches and their structural consequences
There are three primary session management models, and the choice between them determines the downstream properties of the authentication system in ways that are not reversible without a substantial rewrite.
Server-side sessions store session data on the server — in memory, in Redis, in a database — and issue the client a session ID (typically a cryptographically random string stored in an httpOnly cookie). Every authenticated request presents the session ID, the server looks up the session data, and the application proceeds. The defining property of server-side sessions is that revocation is instant and total: deleting a session record from the session store immediately invalidates the session, regardless of any tokens held by the client. The cost of this property is that every authenticated request requires a session store lookup — a network round-trip to Redis or a database query that adds latency to every request and creates an operational dependency. The session store is a single point of failure: if Redis is unavailable, no authenticated requests can be processed. Horizontal scaling requires a shared session store (or session affinity, which constrains the load balancer). The key architectural consequence of server-side sessions is that the session store becomes infrastructure that must be operated, scaled, and made highly available — a dependency that does not exist when the application first deploys but is load-bearing when the application reaches production scale.
Stateless JWT-based sessions encode session data directly into a signed token that the client holds. The server verifies the signature on every request and trusts the claims inside the token without any server-side storage. The defining property of stateless JWTs is that there is no session store lookup — verification is a cryptographic operation that completes in microseconds with no network dependency. The cost of this property is that revocation is structurally difficult. A JWT remains valid until it expires. If the token is compromised, the only way to prevent its use is to maintain a server-side revocation list (a blocklist of revoked token IDs) — which reintroduces the session store dependency that statelessness was meant to eliminate, or to set a short token lifetime (15 minutes is common for access tokens) and issue a longer-lived refresh token. The refresh token architecture introduces its own decisions: where the refresh token is stored, how refresh token rotation works (single-use vs. multi-use), and how the refresh token is invalidated on logout. The key architectural consequence of stateless JWTs is that the token payload is a schema under the application's control, which means every field added to the token payload is an implicit schema decision with the accumulation properties described above — and that the access token lifetime is a revocation policy with a maximum-breach-window property that must be chosen deliberately, not defaulted.
Federated identity through OAuth 2.0 + OpenID Connect delegates the authentication assertion to an external identity provider. The application does not verify a password or manage user credentials — it receives an ID token from the IdP (an OIDC JWT signed by the IdP's keys) and optionally an access token for calling the IdP's user info endpoint. The defining property of federated identity is that it separates authentication (who is the user, verified by the IdP) from authorization (what is the user allowed to do, determined by the application). SSO, MFA, and social login are first-class capabilities in this model — they are features of the IdP, not the application. The cost of this property is the redirect flow: authentication requires multiple HTTP round-trips through the IdP, which adds latency to the initial authentication and creates a dependency on the IdP's availability. The key architectural consequence of federated identity is that the user's canonical identifier is the IdP's subject claim (a stable opaque string the IdP assigns), not the email address the application may have used to identify users before federation. Any existing application that adds an IdP must reconcile its existing user identity model with the IdP's identity model — and the cost of that reconciliation is determined by how tightly the existing model was coupled to its original identity assumptions.
Token design: the decisions inside the choice
Once the session management model is chosen, the token design decisions are the next layer. For JWT-based systems, these decisions are consequential in ways that are not visible until the system grows.
Signing algorithm: RS256 vs HS256. HS256 (HMAC-SHA256) uses a shared secret to sign and verify tokens — the same key both mints tokens and verifies them. Any service that needs to verify tokens must hold the secret, which means the secret must be distributed to every verifying service. RS256 (RSA-SHA256) uses a private key to sign tokens and a public key to verify them — only the token-minting service holds the private key, and any service can verify tokens by downloading the public key from a JWKS endpoint. The structural consequence: in a single-service application, HS256 is simpler and the key distribution problem is manageable. In a multi-service architecture where multiple services verify tokens independently, RS256's public-key distribution model is operationally simpler — the JWKS endpoint replaces secret distribution. The choice of signing algorithm determines the key rotation procedure: rotating an HS256 key requires updating the secret on every verifying service simultaneously (or accepting a brief period where some services reject tokens signed with the new key); rotating an RS256 key pair requires a grace period during which both old and new public keys are valid, which JWKS endpoints support natively.
What goes in the JWT payload — and what must not. The JWT payload is the most consequential token design decision. Claims added to the payload are baked into every token issued until the consuming code is changed, which means the payload is a forward-compatibility contract: every field you add is a field you must support in every verifying service for the lifetime of any token that contains it. The rule that JWT payloads accumulate is not theoretical — it is observed in every codebase that uses JWTs for session management past the two-year mark. The typical accumulation: user ID and email in the first implementation; role when the first RBAC feature is added; organization ID when the first multi-tenant feature is added; subscription tier when the first pricing tier is added; feature flags when the first experiment is run; a iat claim used as a last-password-change check. Each addition made sense at the time. Together, they produce a payload that a new engineer cannot read without asking why each field is there.
The explicit decision about what NOT to put in the JWT is as important as what to include. Mutable application state — subscription status, feature flags, experiment cohort assignments, user preferences — should not be in a JWT with a multi-hour lifetime, because the token will serve stale data for the duration of its validity. Authorization data that changes faster than the token lifetime must either be fetched from the database on every request (which partially defeats the purpose of a stateless token) or managed with a short token lifetime. High-cardinality user attributes — email address, display name, avatar URL — should not be in the token at all if they can change, because changing them requires either a forced re-login or a token refresh cycle, neither of which the user expects when they update their profile.
Access token lifetime and the revocation window. A 24-hour access token means that a compromised token is usable for up to 24 hours after the compromise is discovered. A 15-minute access token limits the breach window to 15 minutes but requires a working refresh token mechanism or constant re-authentication. The access token lifetime is a security policy with a maximum-breach-window property — and it must be explicitly chosen rather than left at the library default, which is often set for convenience rather than security. The threat model determines the acceptable breach window; the acceptable breach window determines the token lifetime; the token lifetime determines the refresh token architecture required.
Token storage: the security trilemma
Where tokens are stored on the client is a decision with three options, each accepting a different security trade-off. The decision is typically made once, at first implementation, and is expensive to change because changing token storage requires migrating all active sessions.
localStorage stores the token as a JavaScript-accessible string. Any script running in the page can read it — the application's own scripts, third-party analytics scripts, injected content from a compromised CDN dependency, and a malicious script injected through an XSS vulnerability anywhere in the application. localStorage is persistent across browser sessions by default. The risk it accepts: a single XSS vulnerability anywhere in the application surface — a React component that renders unsanitized user input, a third-party script that is itself compromised, a browser extension with permission to read page content — is sufficient to exfiltrate all stored tokens for all users who have ever visited the page. XSS is consistently in the OWASP Top 10. The benefit it provides: simplicity of implementation and compatibility with single-page application architectures that make requests from JavaScript without the page navigating.
httpOnly cookies store the token in a cookie that the browser sends automatically on every request but that JavaScript cannot read. The HttpOnly flag instructs the browser to withhold the cookie value from document.cookie. An XSS vulnerability cannot read an httpOnly cookie. The risk accepted by httpOnly cookie storage is CSRF (Cross-Site Request Forgery): a malicious page on a different origin can trigger a state-changing request to the application, and the browser will send the cookie automatically. CSRF is mitigated by the SameSite cookie attribute (Strict prevents the cookie being sent on cross-site requests; Lax prevents it on non-safe-method cross-site requests) and by CSRF tokens. The SameSite attribute behavior is well-supported in modern browsers but has compatibility nuances: Strict breaks login flows that redirect from a third-party to the application (the cookie is not sent on the first request after the redirect). The benefit provided: httpOnly cookies are the default recommendation of the OWASP authentication cheat sheet and the approach that survives most security audits without a finding. The storage decision and the SameSite policy belong in the authentication strategy ADR so the security team can verify at audit time that the implementation matches the documented policy.
In-memory storage with a Backend-for-Frontend (BFF) pattern keeps tokens in JavaScript memory (never in localStorage or sessionStorage), combined with a BFF server that holds long-lived tokens and issues short-lived cookies to the browser. Tokens stored in memory are lost on page refresh — the user must re-authenticate or the BFF must issue a new session token — which prevents token persistence across sessions by design. This is the most secure approach for high-value applications where token exfiltration is a critical threat, but it adds the operational complexity of the BFF server and requires that every API call be proxied through the BFF rather than called directly from the browser. The BFF pattern is an architectural decision with implications beyond authentication — it determines the shape of the API surface, the latency profile of API calls, and the operational footprint. It should be documented explicitly rather than adopted as a de facto pattern because the authentication implementation happened to be structured that way.
The SSO migration cost and how to reduce it
SSO is not a feature that is added alongside existing authentication — it is a change to the identity model of the application. The cost of that change is proportional to how tightly the application's data model, authorization logic, and session design are coupled to the original identity assumptions. The new CTO who inherits a codebase two years after its initial authentication decisions were made cannot read the SSO migration cost from the code — it is only discoverable by attempting the migration.
The three coupling patterns that make SSO migrations expensive, and the authentication strategy decisions that prevent them:
Email as identity. Using email address as the primary user identifier — as a database primary key, as the join key in foreign key relationships, or as the canonical user reference in any stored data — creates a migration problem when an SSO IdP's user identifier is a stable opaque subject claim, not an email address. Email addresses change (users change their corporate email when they change roles), are shared (a company's email domain changes in an acquisition), and are not guaranteed unique across IdPs (two IdPs can independently assert different users with the same email address). The authentication strategy ADR should document the canonical user identifier explicitly: a stable, opaque, never-changing identifier that the application owns, with email as an attribute that can change without affecting identity. This decision, made at project start, reduces SSO migration cost from a user-ID migration to a lookup table addition.
Authorization data in the session layer. When role, permission, and organizational membership information lives in the JWT or session store (rather than in the database), the SSO integration must arrange to populate that information from an authoritative source when the IdP authenticates the user. If the information is in the IdP's claim set (Okta groups, Azure AD roles), the mapping is straightforward. If the information is in the application database (the user's subscription tier is a column in the application's users table, not an Okta attribute), the session build process must merge IdP claims with application data on every authentication. This is not a fatal design — it is a reasonable design — but it must be documented so that the SSO integration engineer understands the merge requirement rather than discovering it by observing that role checks fail for SSO users.
Authentication-specific state accumulated in the general session. Server-side sessions that accumulate application state over the lifetime of the session — UI preferences, wizard progress, partially completed forms — make SSO federation complex because the IdP authentication establishes a new session that lacks the accumulated state of the old session. The authentication strategy ADR should define the boundary between authentication state (what the IdP can assert) and application state (what the application owns), so that SSO integration can target the authentication layer without inadvertently losing the application state layer. Feature flag decisions documented alongside the authentication strategy clarify whether flags live in the identity layer or the application layer — a distinction that determines whether an IdP attribute or a database query populates them in an SSO flow.
Multi-tenancy and the authorization model
The authorization model — how the application decides what an authenticated user is allowed to do — is logically separate from authentication but is structurally coupled to the session design. The authentication strategy ADR should document the authorization model because the two are co-designed at implementation time and the decoupling between them (or lack of it) determines the maintainability of the authorization system.
The three authorization model families and their structural consequences:
Flat role-based access control (RBAC). The user has a single role (admin, editor, viewer) stored in the session or the database, and application code branches on the role to determine what operations are permitted. Flat RBAC is easy to implement and easy to understand at small scale. Its structural limitation is that roles are coarse-grained: as the product grows, new capabilities require either new roles (which proliferate) or the addition of per-permission flags alongside the role (which produces an authorization model that is neither clean RBAC nor clean permission-based access control). The authentication strategy ADR should document the role set explicitly and the decision to use flat RBAC rather than a permission-based model, so the first engineer who needs to add a "billing admin" role can assess whether to add it to the role set or to introduce per-permission flags, with the context of the original decision rather than just the current code.
Multi-tenant isolation. In a multi-tenant SaaS application, every data access must be scoped to the authenticated user's tenant. The isolation mechanism — a per-query WHERE org_id = ? condition, a row-level security policy in the database, a middleware that enforces tenant scope on every request — is an authorization decision with security consequences. Tenant isolation failures are a class of security vulnerability where one tenant's data is visible to another tenant's users. The isolation mechanism and its enforcement scope (does it cover every code path, or are there bypass paths?) should be documented in the authentication strategy ADR so that the security team can audit it explicitly and any engineer adding a new data access pattern knows the enforcement requirement. Platform teams who provide shared infrastructure to product teams need the multi-tenancy model documented at the platform level so product teams do not implement inconsistent isolation.
Authorization service vs. inline permission checks. As permission complexity grows, inline permission checks scattered across the codebase (if user.role == 'admin' or user.permissions.contains('delete_users')) become difficult to audit and maintain — the full permission model is only visible by searching the entire codebase. An authorization service (a library like Casbin, a sidecar like OPA, or a managed service like Permit.io) centralizes permission decisions and makes the full policy auditable in one place. The trade-off is operational complexity (the authorization service is another dependency to operate) and latency (each permission check is a network call or an in-process policy evaluation). The decision to use inline checks vs. a centralized authorization service should be explicit, with the complexity threshold at which the switch would be reconsidered documented in the ADR.
Compliance: SOC 2, GDPR, and the authentication audit
Compliance requirements do not drive most initial authentication decisions — they arrive later, when the company begins a SOC 2 audit, when GDPR enforcement reaches a customer's jurisdiction, or when a pen test report lists findings against the authentication layer. The authentication strategy ADR should document the compliance commitments the implementation satisfies so that the compliance team can reference the ADR rather than auditing the code, and so that any engineer who changes the authentication implementation understands which compliance controls must be preserved.
The SOC 2 Trust Services Criteria that directly address authentication (CC6 series — Logical and Physical Access Controls):
CC6.1: Logical access security software. The application restricts logical access to the system through authentication controls, and those controls are documented. The authentication strategy ADR is the documentation that satisfies this criterion for the software layer. It should name the session management model, the token lifetime, the password policy (if applicable), and the MFA implementation.
CC6.2: Access provisioning and de-provisioning. New user accounts are provisioned with appropriate access levels, and access is de-provisioned when a user leaves. The authorization model documented in the authentication strategy ADR describes the role and permission structure that access provisioning operates against. If SSO with IdP-managed groups is in scope, the provisioning and de-provisioning flow through the IdP is described here.
CC6.3: Role-based access. Access is restricted to the minimum necessary for each role. The flat RBAC or permission-based model described in the authentication strategy ADR is the artifact the auditor reviews for this criterion. An undocumented authorization model is a finding; a documented model with a clear role set and the principle of least privilege applied is evidence of control.
The GDPR implications of session design are less commonly documented but materially consequential. Sessions contain personal data (at minimum, the user's identifier; in practice, often name, email, role, and behavioral state). The data retention decision for session data should be explicit: how long are sessions retained in the session store after expiry, how long are session audit logs retained, and what is the legal basis for the retention period. A session store that retains expired sessions indefinitely (because the expiry policy was implemented in the application layer without a corresponding TTL on the Redis keys) creates a GDPR data minimization issue. The authentication strategy ADR is the natural place to document the session data retention policy alongside the session management model, because the two are implemented together.
Session audit logs — records of which user authenticated, when, from which IP address, and what authentication events (logout, password change, MFA enrollment) occurred — are evidence for SOC 2 CC6.x and are also personal data under GDPR. The log retention period and the log storage location (application logs, a SIEM, an audit trail table in the database) should be documented. Post-incident reviews of authentication incidents (a token exposure, an account takeover, an unauthorized access event) require session audit logs to reconstruct the attack timeline; the audit log design is the authentication strategy decision that determines whether that reconstruction is possible.
What a complete authentication strategy ADR looks like
The five sections of an authentication strategy ADR and the decisions each section records:
Section 1: Session management model. The chosen model (server-side sessions, stateless JWT, federated OIDC) with the alternatives evaluated and the rejection reason for each. The specific library or provider chosen and the version. For server-side sessions: the session store backend, the session ID generation method, and the high-availability strategy. For JWT: the signing algorithm, the key rotation policy, and the refresh token architecture. For OIDC: the identity provider, the flow used (authorization code with PKCE is the current standard; implicit flow is deprecated), and the claim mapping from IdP claims to application user attributes.
Section 2: Token design. The JWT payload schema: every claim, its type, its source (application database, IdP claim, computed at token issue time), and the explicit list of what the claim is used for. The token lifetime — access token and refresh token separately, with the reasoning for each lifetime value (the accepted breach window, the UX constraint that prevents a shorter lifetime). The explicit list of what is NOT in the JWT and why (mutable state, high-cardinality attributes). The revocation policy: whether revocation is supported, the mechanism (blocklist, token rotation, short lifetime only), and the maximum revocation latency.
Section 3: Token storage and security. The storage mechanism (httpOnly cookies, localStorage, in-memory + BFF) with the specific security trade-off accepted. The SameSite and Secure cookie attributes and the CSRF mitigation strategy. The CORS policy that is coherent with the storage decision. A reference to the pen test findings this design addresses (or the findings that remain as known accepted risks with a compensating control).
Section 4: Authorization model. The role or permission set with the definition of each role. The multi-tenancy isolation mechanism and the scope of its enforcement (does it apply to all data access paths, or are there exceptions). The authorization check API (the function or middleware that application code calls to check permissions) and the policy for where authorization checks are placed. Whether a centralized authorization service is in scope and the complexity threshold at which it would be adopted. The SSO group-to-role mapping if OIDC federation is in scope.
Section 5: Compliance commitments. The SOC 2 criteria satisfied and the specific implementation that satisfies each (the authentication ADR is the evidence artifact for CC6.1 and CC6.3). The GDPR legal basis for session data processing. The session data retention policy — how long active sessions are retained, how long expired session data is retained in the session store, and how long session audit logs are retained. The session audit events logged (login, logout, token refresh, password change, MFA events, access denied events) and their storage location. The known compliance gaps with an explicit statement of acceptance and a planned remediation date.
Finding authentication decisions in AI chat history
Authentication decisions are present in AI chat history in four session types, each capturing a different layer of the authentication strategy at a different point in the system's life.
The initial setup session is the highest-value recovery target. "Should I use JWT or session cookies for my Node.js API?" "What is the difference between OAuth 2.0 and OpenID Connect?" "Should I store the JWT in localStorage or an httpOnly cookie?" "What claims should I put in my JWT payload?" "Should I build authentication myself or use Auth0?" These questions are asked once, at project start, and the answers determine the session management model, the token storage decision, and the library or provider selection. The initial setup session contains the explicit rejection reasons for each alternative — "I chose httpOnly cookies because the Auth0 docs said localStorage is vulnerable to XSS" — which is the exact reasoning that disappears into the void between implementation and the first security audit.
The 'add SSO' session reveals the SSO migration cost discovered under real constraint. "Our enterprise customer requires Okta SSO — how do we add SAML support?" "We use JWTs — how do we integrate an identity provider without rewriting the auth layer?" "How do we handle users who exist in our database and also exist in the IdP?" "What is the difference between a SAML assertion and an OIDC ID token?" These sessions contain the SSO migration decisions — the lookup table design, the claim mapping strategy, the user ID reconciliation approach — which are made under commercial pressure and are therefore rarely documented. They are also the sessions most likely to contain the discovery of technical debt accumulated since the initial authentication decision: the 14-field JWT, the email-as-primary-key problem, the feature flags in the token.
The security incident session documents the revocation policy and the security response procedure. "One of our JWTs was exposed in a log — how do we invalidate it?" "Our session store was compromised — how do we force all users to re-authenticate?" "Someone discovered our JWT secret is in the git history — what do we do?" "A pen tester found our refresh tokens don't rotate — how do we fix this?" These sessions reveal the revocation architecture (or its absence) under incident pressure. They contain the decisions made about whether to implement a blocklist, how to force logout, and what the remediation procedure is — decisions that belong in the authentication strategy ADR alongside the original session management model, because the incident is the mechanism by which the revocation policy was actually determined.
The compliance preparation session documents the compliance requirements and the specific controls added. "What authentication controls does SOC 2 require?" "Does our current session management satisfy GDPR Article 32?" "Our pen tester flagged our httpOnly cookie is missing the Secure flag — what else should we check?" "What is the session timeout requirement for SOC 2 CC6?" These sessions contain the compliance-authentication mapping — which criteria apply, what the current implementation satisfies, and what changes were made to close gaps. This is exactly the content that belongs in Section 5 of the authentication strategy ADR, and it is content that is almost never written anywhere except the AI chat where the question was first worked through.
Three months of AI chat history from an engineering team building a SaaS application will contain all four of these session types: the initial authentication setup in month one, the first pen test finding in month two (often an httpOnly or SameSite flag missing, or a CSRF token absent), and the first SSO requirement in month three as the first enterprise sales conversation begins. The WhyChose extractor identifies these sessions because they contain the characteristic language of authentication decisions under constraint: specific algorithm names (RS256, HS256, PKCE), specific security terms (XSS, CSRF, CORS, SameSite), specific protocol terms (SAML NameID, OIDC sub, access token, refresh token, ID token), and specific incident language ("how do I invalidate", "we were compromised", "the pen tester found"). These are the sessions that contain the reasoning behind the 14-field JWT, the email-as-primary-key, and the 24-hour token lifetime — the decisions that determine the six-week SSO migration cost that arrives eighteen months later.
Further reading
- Decisions that never get written down — the initial authentication setup session, the first SSO integration session, the security incident session, and the compliance preparation session are each decision events that produce institutional knowledge without producing documentation; the institutional knowledge lives in the engineer who participated and is lost when they leave, change roles, or forget
- Security ADRs: from threat model to compliance evidence — the authentication strategy ADR and the security threat model ADR are the same system described at different layers; the threat model names the threats (XSS, CSRF, token exfiltration, session fixation), the authentication strategy documents the controls deployed against each threat, and both are needed to satisfy a SOC 2 auditor's request for logical access control evidence
- The data retention decision record — session data is personal data under GDPR, and the session data retention policy is part of the authentication strategy; how long expired sessions are retained in the session store, how long session audit logs are retained, and what the legal basis for each retention period is belong in both the data retention ADR and the authentication strategy ADR as co-documented decisions
- The feature flag decision record — the decision to put feature flags in the JWT payload is a co-decision between the authentication strategy and the feature flag strategy; flags in the JWT become stale for the token's lifetime, but fetching them from the database on every request partially defeats the purpose of stateless tokens; the resolution (short token lifetime, token refresh on flag change, or flags fetched from the database outside the token) belongs in both ADRs as a documented cross-cutting constraint
- The API versioning decision record — authentication token format is an API versioned by the signing key and the claim schema; adding a claim, removing a claim, or changing the signing algorithm is effectively an API version change for every consuming service; the token design ADR and the API versioning ADR should document the token versioning policy (whether tokens carry a version claim, how consuming services handle tokens from multiple versions during a transition, and the deprecation policy for old token formats)
- ADRs for platform teams: how infrastructure decisions become constraints for product teams — when the authentication service is a platform component maintained by a platform team, the session management model, token format, signing algorithm, and claim schema are platform constraints; product teams implement authorization checks against the token format the platform provides, and changes to the token format are breaking changes that must be coordinated across all consuming product teams; the platform authentication ADR communicates these constraints before product teams build against them
- The database migration strategy decision record — changing the user identity model (from email as primary key to a stable opaque user ID) is a database migration problem; the expand-contract pattern, the large table migration policy, and the rollback strategy for the user table migration are the database migration ADR decisions that determine the safety of the identity model migration that SSO requires; the two ADRs are co-dependent at the moment the SSO migration plan is written
- Postmortem ADRs: converting incident decisions into decision records — authentication incidents (token exposure, session store compromise, account takeover, unauthorized privilege escalation) are the natural source events for authentication strategy ADR updates; the postmortem identifies the gap in the authentication design, the ADR update records the control added to close it, and the next engineer who asks why the refresh token rotation policy exists can read the postmortem reference in the ADR rather than being told a verbal story
- The startup decision log: first year — authentication decisions are among the highest-value decisions to document in the first year of a startup; the session management model, the token storage decision, and the authorization model chosen at project start have the longest tail of consequences of any infrastructure decision made in year one, because they determine the SSO migration cost discovered in year two and the compliance posture assessed in year three
- Three months of AI chat history, undocumented — authentication decisions are reliably present in AI chat history in four session types: the initial setup session (session management model, token storage), the SSO integration session (identity model coupling, claim mapping), the security incident session (revocation policy, token exposure response), and the compliance preparation session (SOC 2 criteria, GDPR session data retention); these sessions contain the reasoning behind every field in the JWT payload and every security trade-off accepted in the token storage decision
- The new-CTO onboarding problem: when nobody can tell you why — a technical leader who inherits a codebase with a JWT containing 14 fields, email as primary key, and a 24-hour token lifetime cannot determine from the code alone why each field is in the JWT, why email was chosen as the identity anchor, or what the breach window of the token lifetime was intended to be; the authentication strategy ADR is the document that makes the design legible without requiring an interview with the original engineer
- ADRs for wrong constraints: when the assumption was false — the most common false assumption in authentication ADRs is "we will add SSO later and it will be straightforward"; this assumption is false when the identity model uses email as a primary key, when authorization data is deeply embedded in the JWT payload, or when the session accumulates mutable state; documenting this assumption explicitly in the authentication strategy ADR at project start makes it possible to revisit it when the SSO requirement first appears, rather than discovering it is false in the middle of an enterprise sales process
- Nygard ADR template — the authentication strategy ADR's five sections (session management model, token design, token storage, authorization model, compliance commitments) each map to the Nygard format's Context, Decision, and Consequences structure; the token design section's explicit list of what is NOT in the JWT maps to the Consequences section's "negative consequences" subsection — the design constraints accepted rather than the capabilities gained
- WhyChose extractor — authentication decisions are reliably present in AI chat history in four session types: the initial setup session (JWT vs session cookies, localStorage vs httpOnly cookie, Auth0 vs custom), the SSO integration session (SAML vs OIDC, claim mapping, user ID reconciliation), the security incident session (token revocation, forced logout, refresh token rotation), and the compliance preparation session (SOC 2 CC6 controls, GDPR session data retention); the extractor identifies these sessions by the characteristic language of authentication decisions — specific protocol names (PKCE, SAML NameID, OIDC sub), specific security terms (XSS, CSRF, httpOnly, SameSite), and specific incident language (how do I invalidate, how do I force logout, the pen tester found)