GoodNotes Architect Journal
🏠 Index 1. Single Server 2. Selecting DB 3. Relational & SQL 4. ACID Integrity 5. NoSQL Types 6. Scaling Guide 7. Load Balancing 8. SPOF & HA 9. API Design 10. Comm Protocols 11. TCP & UDP 12. REST Design 13. GraphQL Architecture 14. Authentication Protocols 15. JWT & OAuth 2 16. Authorization Models
System Design Chapter 15

Sessions, JWT Tokens, & OAuth 2 / OIDC

Stateful Sessions, Stateless JWT Verification, Access vs Refresh Lifecycles, & OAuth 2 Delegation Flow

β˜… Store refresh tokens in HttpOnly cookies! JWT signatures are verified locally with zero DB lookups.

1 Stateful Session-Based Authentication

In traditional web applications, authentication is Stateful. The server creates and retains an active session record in a centralized fast data store (e.g., Redis) for every logged-in client:

πŸͺœ Session-Based Authentication: 8-Step Stateful Lifecycle
πŸ‘€
User / Browser
Client Agent
πŸ–₯️
Web Server
App Backend
πŸ—„οΈ
Session Store
Redis Cluster

1 Initial Credentials Submission

Browser βž” Server
User submits credentials (POST /login { username, password }) over HTTPS.

2 Create Session Record

Server βž” Redis
Server verifies password hash, generates a secure random Session ID, and writes user context to Redis (TTL 24h).

3 Session Persistence Confirmed

Redis βž” Server
Redis confirms session persistence and returns the unique cryptographic session_id: sess_98432a1.

4 Set Secure Cookie Header

Server βž” Browser
Server responds: Set-Cookie: sid=sess_98432a1; HttpOnly; Secure; SameSite=Strict.

⚑ Subsequent Protected Requests Loop ⚑

5 Automatic Cookie Attachment

Browser βž” Server
Browser sends request to GET /api/dashboard; HTTP client attaches cookie Cookie: sid=sess_98432a1 automatically.

6 Session Lookup Query

Server βž” Redis
Server queries cache: GET session:sess_98432a1 to fetch user roles, permissions, and status.

7 Return Session State

Redis βž” Server
Redis returns active session payload (e.g. { userId: 42, role: β€œadmin”, exp: … }).

8 Authorized Payload Delivery

Server βž” Browser
Server authorizes the request and returns the protected dashboard data with 200 OK.

2 Stateless Token-Based Authentication (JWT Bearer Flow)

To scale across horizontally distributed microservices without querying a centralized session store on every HTTP call, modern systems use Stateless JWT Bearer Tokens:

🧩 The 3 Parts of a JSON Web Token (JWT)

1. Header (Alg & Type)

{ β€œalg”: β€œRS256”, β€œtyp”: β€œJWT” }

Base64URL encoded; defines signature algo.
2. Payload (Claims)

{ β€œsub”: β€œ42”, β€œrole”: β€œadmin”, β€œexp”: 171400 }

Base64URL encoded; carries non-sensitive claims.
3. Cryptographic Signature

HMACSHA256(b64(H) + ”.” + b64(P), secret)

Guarantees integrity; prevents tampering.
⚑ Stateless JWT Bearer 6-Step Verification Flow
πŸ“±
Client App
SPA / Mobile
πŸ›‘οΈ
Auth Server
Issues Tokens
🌐
API Microservice
Zero-DB Verifier

1 Authentication Request

Client βž” Auth Server
Client sends user credentials (POST /auth/login).

2 Validate & Sign Token

Auth Server Internal
Auth Server verifies credentials against DB, encodes claims, and signs the JWT using its Private Key.

3 Issue Signed JWT

Auth Server βž” Client
Returns JWT token payload to the client for subsequent API calls.

⚑ Zero-Lookup API Consumption ⚑

4 Bearer Token Request

Client βž” API Microservice
Client sends request with header: Authorization: Bearer <signed_jwt_token>.

5 Local Signature Verification (No DB Hit!)

API Microservice Internal
API Server computes cryptographic check with Public Key / Shared Secret: verifies expiry, signature, and user claims with 0 database I/O.

6 Direct Resource Response

API Microservice βž” Client
API returns requested resource directly (200 OK).

πŸš€ Core Advantage

Massive Horizontal Scalability: Any API microservice across multiple data centers can independently authenticate requests using only a cached public key.

⚠️ Core Trade-Off

Revocation Difficulty: Because verification is completely stateless, invalidating a leaked token before its expiration requires maintaining a distributed blacklist or using very short TTLs.

3 Access & Refresh Token Dual-Lifecycle

To balance security (limiting leak damage) and user experience (avoiding frequent re-logins), modern architectures adopt a Dual-Token Strategy:

⚑ Access Token

15 min – 1 hr

Short-lived; sent with every API request via Authorization: Bearer header. If intercepted, attacker window is strictly minimized.

πŸ”„ Refresh Token

7 to 30 days

Long-lived; stored exclusively in secure HttpOnly cookies; used only at /auth/refresh to mint fresh access tokens.

πŸ”„ Access & Refresh Token Silent Renewal Sequence
πŸ“±
Client App
Browser Storage
πŸ›‘οΈ
Auth Server
Issuer & Refresher
🌐
Resource Server
API Service

1 Initial Dual-Token Issuance

Auth Server βž” Client
Auth Server responds to valid login with: Access Token in JSON response body (15m) + Refresh Token in HttpOnly cookie (30d).

2 Expired Access Token Rejection

Resource Server βž” Client
Client calls API after 16 mins; Resource Server rejects expired token signature: 401 Unauthorized (jwt expired).

3 Silent Background Refresh Request

Client βž” Auth Server
HTTP interceptor traps 401, pauses pending requests, and calls POST /auth/refresh (sending HttpOnly refresh cookie).

4 Token Rotation & New Access Token

Auth Server βž” Client
Auth Server checks token validity against DB/redis revocation table, rotates refresh token, and returns a fresh Access Token.

5 Transparent Request Replay

Client βž” Resource Server
Client automatically replays the original failed request with the new access token; user experiences zero disruption!
🚨 Essential Security Golden Rule: Cookie Flags

Never store Refresh Tokens in localStorage or sessionStorage!
Any Cross-Site Scripting (XSS) vulnerability allows attackers to exfiltrate local storage items. Always store Refresh Tokens inside HttpOnly, Secure, SameSite=Strict cookies so client-side JavaScript cannot access them.

4 OAuth 2.0 Authorization Code Flow (Delegation)

OAuth 2.0 is an Authorization Delegation Framework enabling a third-party application to access user resources from an API without ever exposing user credentials:

πŸ›‘οΈ OAuth 2.0 Authorization Code Grant: 8-Step Delegation Flow
πŸ‘€
User
Resource Owner
πŸ“±
Your App
OAuth Client
πŸ”‘
Auth Server
Google OAuth
πŸ“
Resource API
Google Drive API

1 User Initiates Third-Party Connection

User βž” Your App
User clicks β€œConnect Google Drive” inside Your App to import their cloud files.

2 Browser Redirect to Consent Dialog

Your App βž” Google OAuth

3 Consent Confirmation

User βž” Google OAuth
Google prompts user: β€œGrant Your App read-only access to Drive?” User clicks Allow.

4 Authorization Code Returned via Redirect

Google OAuth βž” Your App

5 Backend Code Exchange (Direct Server-to-Server)

Your Backend βž” Google OAuth
App backend securely POSTs: code=spl_auth_code_91823 + client_secret to Google token endpoint.

6 Access Token Issued

Google OAuth βž” Your Backend
Google authenticates client secret and returns Access Token with scope drive.readonly.

7 Scoped API Data Request

Your App βž” Google Drive API
App queries Drive API with: Authorization: Bearer <access_token>.

8 Protected Files Returned Securely

Google Drive API βž” Your App
Google Drive API validates token permissions and safely delivers user files without ever revealing Google password!

5 OpenID Connect (OIDC): Adding Identity & Authentication

OpenID Connect (OIDC) is an identity layer built directly on top of OAuth 2.0 that allows clients to verify user identity and obtain verified profile information via a digitally signed ID Token (JWT format):

πŸ›‘οΈ OAuth 2.0 Alone

Focus: Authorization / Delegation
Answers: β€œWhat access does this app have?” Returns an Access Token intended for Resource Servers (APIs).

πŸ†” OAuth 2.0 + OIDC

Focus: Authentication / Identity
Answers: β€œWho is the user?” Returns an ID Token (JWT) intended for the Client to read user identity claims.

πŸ†” OpenID Connect (OIDC) 8-Step 'Sign in with Google' Flow
πŸ‘€
User
End-User
πŸ“±
Client App
Frontend SPA
πŸ”‘
IdP (OIDC)
Google Identity
πŸ–₯️
App Backend
Session Creator

1 User Clicks β€˜Sign in with Google’

User βž” Client App
User clicks social login button on your website.

2 Redirect with openid Scope

Client App βž” Google IdP
Redirects to Google authorization endpoint with standard scope: scope=openid profile email.

3 User Authenticates & Approves

User βž” Google IdP
User logs into Google and confirms sharing profile/email details with Your App.

4 Authorization Code Returned

Google IdP βž” Client App
Google redirects to application redirect URI with temporary authorization code.

5 Code Exchange for Dual Tokens

App Backend βž” Google IdP
Backend exchanges auth code with Google token endpoint (POST https://oauth2.googleapis.com/token).

6 IdP Returns ID Token + Access Token

Google IdP βž” App Backend
Google returns: id_token (signed JWT with email, name, avatar) + access_token.

7 Verify Signature & Link User Account

App Backend Internal
Backend verifies ID token signature using Google’s public JWKS certificates; extracts user profile and creates local session.

8 Authenticated Session Established

App Backend βž” Client App
User is logged in seamlessly with verified identity; welcome screen rendered!

6 Single Sign-On (SSO) & Federated Identity Architecture

β€œ
Single Sign-On (SSO) is a seamless User Experience and architectural trust pattern, not a standalone transport protocol. Users authenticate once with a central Identity Provider (IdP) to access all enterprise apps without re-entering credentials.
β€” Identity & Access Management (IAM) Core Principle
🌐 Enterprise SSO Hub-and-Spoke Federated Ecosystem
πŸ‘€
Enterprise User

Single Login Entry

MFA Challenge βž”SAML / OIDC Auth
πŸ›‘οΈ
Central Identity Provider (IdP)

Okta β€’ Microsoft Entra ID (Azure AD) β€’ Google Workspace β€’ Keycloak

SAML 2.0 AssertionsOIDC ID Tokens

⬇️ Cryptographically Federated Trust (Zero Password Sharing) ⬇️

πŸ“§
Google Workspace / Gmail
SAML 2.0 Web SSO Assertion
βœ“ Auto Logged In
πŸ“
Enterprise Box / Drive
OIDC JWT Identity Claims
βœ“ Auto Logged In
πŸ’¬
Slack / MS Teams
SCIM User Provisioning + SAML
βœ“ Auto Logged In
πŸ™
GitHub Enterprise / Jira
OIDC / OAuth 2 Federated IAM
βœ“ Auto Logged In

πŸ’‘ Centralized Security Control: When an employee departs, deactivating their account at the central IdP instantly terminates access across all 200+ connected enterprise applications without individual app de-provisioning.

7 Architectural Comparison: Sessions vs. JWTs vs. OAuth 2 / OIDC

Comprehensive decision matrix to select the right authentication and authorization paradigm for your system:

DimensionStateful SessionsStateless JWT TokensOAuth 2.0 / OIDC
Primary GoalUser Authentication (AuthN)User Authentication (AuthN)Delegated Authorization + Identity
State StorageServer-side (Redis, Database cluster)Client-side (Signed cryptographic token payload)Decentralized tokens with IdP key verification
Verification CostDatabase / cache network round-trip on every call0 DB Lookups: Pure local CPU signature verificationPublic key (JWKS) cached verification or token introspection
Revocation SpeedInstant: Delete session key from RedisHard: Requires token blacklists or short expiry TTLsRevoke token at IdP / token introspection endpoint
Payload SizeTiny cookie (32-byte session ID)Medium-large (500B – 2KB HTTP header overhead)Medium-large (Access token + ID token JWTs)
Cross-Domain / MicroservicesHard (Requires sticky sessions / shared Redis)Native: Passes seamlessly across microservicesNative: Federated across independent organizations
Best Suited ForMonolithic SSR web apps, banking & finance portalsHigh-scale microservices, mobile apps, SPA dashboardsThird-party integrations, enterprise SSO, Google sign-in