Like many developers, I used “Login with Google” everywhere — but if someone asked how it actually works, I couldn’t confidently explain it.
This blog is a learning journey, not a textbook.
It shows how things connect, why they exist, and what problem each layer solves.
The First Problem: HTTP Doesn’t Remember You
HTTP is stateless.
That means every request is independent.
So the server doesn’t know:
who you are
whether you logged in before
This is where cookies and sessions enter.
Browser → Request
Server → Response
(no memory by default)Cookies and Sessions
A cookie is just a small piece of data stored in the browser.
A session is data stored on the server.
How they work together
User logs in
Server creates a session
Server sends a
sessionIdcookieBrowser sends that cookie on every request
Cookie: sessionId=abc123Important rule:
Cookies are domain-scoped
Only the domain that created the cookie can read it.
This rule later becomes the backbone of SSO security.
Authentication vs Authorization (Most Confused Topic)
This distinction matters everywhere later.
Authentication → Who are you?
Authorization → What can you do?
// Authentication
if (passwordCorrect) user = authenticated;
// Authorization
if (user.role === "admin") allowDelete();Authentication usually happens once.
Authorization happens on every request.
Why Sessions Store More Than Just an ID
At first it feels like:
“Why not just store sessionId + expiry?”
Because the server must answer questions like:
Is this user admin?
Is the account blocked?
Can this user delete data?
If the server stored only an ID, it would need a DB query on every request.
So sessions store user context:
{
"userId": 42,
"role": "admin",
"isBlocked": false
}Sessions = performance + fast authorization decisions
JWT: Same Idea, Different Tradeoff
JWT moves session data from server to token.
const token = jwt.sign(
{ id: 42, role: "admin" },
SECRET,
{ expiresIn: "30m" }
);Key points:
JWT is signed, not encrypted
Server verifies signature → no DB hit
Stateless, good for APIs
JWT does not replace OAuth or SSO.
It’s just a token format.
The Problem OAuth Was Created to Solve
Before OAuth:
Apps asked for your password
Huge security risk
OAuth introduced one idea:
Don’t share passwords. Share limited permissions.
OAuth is about authorization, not login.
OAuth in One Flow (Simplified)
App redirects user to provider
User logs in + gives consent
Provider gives authorization code
Backend exchanges code for token
Frontend → Google → Auth Code
Backend → Google → Access TokenImportant:
Client Secret never goes to frontend
Browser handles redirects only
What Access Tokens Are Actually For
This was a big realization:
Access tokens are NOT for your app login
They are only for provider APIs.
Example:
Authorization: Bearer ACCESS_TOKENUsed for:
Gmail API
Google Drive
YouTube data
Shopify orders
Facebook posts
Your app login is still handled by your own session.
Access Token vs Session (Not the Same Thing)
Access Token
Issued by provider
Short-lived
Used for external APIs
Session
Issued by your backend
You control expiry
Used for your app login
They live independently.
Refresh Tokens and Silent Login
Access tokens expire quickly for security.
Refresh tokens exist so:
User doesn’t log in again
Backend silently gets new access tokens
Refresh Token → New Access TokenFrontend never sees refresh tokens.
The SSO “Magic”
SSO is not a protocol.
SSO is a result.
The real trick is this:
Apps don’t share login data.
They share a trusted Identity Provider.
What Actually Happens in SSO
User logs in at Identity Provider (IdP)
IdP sets its own cookie
App A redirects to IdP → gets token → creates session
App B redirects to IdP
IdP sees its cookie → no login screen
App B gets its own token → creates its own session
No app ever sees:
IdP cookies
other app sessions
Browser just carries cookies to the correct domain.
No “Master Token” Is Shared
This was a big myth.
IdP keeps a master login session
Each app gets its own token
Each app creates its own session
Browser
├── IdP cookie
├── App A cookie
└── App B cookieThat’s it.
Designing Your Own SSO System
To build SSO, you don’t share cookies across apps.
You create:
One central authentication server
All apps redirect there
That server issues app-specific tokens
This is exactly how:
Google
Company SSO
Okta
Keycloak
work.
Final Mental Model (Everything Connected)
Cookies remember sessions
Sessions store user context
JWT carries signed data
OAuth delegates access
OIDC adds identity
SSO is shared trust, not shared data
Closing Thought
Once you understand this flow,
OAuth stops feeling magical
and starts feeling inevitable.
Every layer exists because the previous one wasn’t enough.
And that’s how modern authentication actually works.