Auth flows, diagrammed
SSO, session cookies, JWT bearer tokens, and OAuth — each one drawn as a picture you can follow.
What are we diagramming?
Authentication can feel abstract because the important parts happen invisibly between the browser, your server, and an identity provider. This guide draws four of the most common login flows as sequence diagrams, so you can literally see who talks to whom, in what order, and what gets passed along.
Authentication vs authorization
Authentication answers 'who are you?' (showing your ID at the door). Authorization answers 'what are you allowed to do?' (whether your ticket lets you into the VIP room). Every flow below does authentication first, then carries proof of it on each later request.
1. Cloudflare Access SSO
SSO (Single Sign-On) means you log in once with one identity provider and then reach many apps without logging in again. With Cloudflare Access, Cloudflare sits in front of your app and handles the whole login — you write no auth code. After login, Cloudflare gives the browser a signed cookie that your app can trust.
Why teams love it
Your app never sees passwords and you write zero login logic. Cloudflare enforces the policy (who is allowed) and only forwards verified requests. Perfect for internal dashboards and admin panels.
2. Session-cookie login
A session is the server's memory of one logged-in visitor. After you log in, the server stores a session record (here in Workers KV) and hands the browser a cookie holding only a random session id. The browser sends that cookie on every later request, and the server looks the id up to know who you are. This is the classic flow for server-rendered web apps.
Keep the cookie safe
Set the cookie as HttpOnly (JavaScript cannot read it), Secure (HTTPS only), and SameSite to reduce CSRF. Give the KV session a TTL so it expires automatically. The cookie itself holds no user data — just the lookup key.
3. JWT bearer-token API auth
A JWT (JSON Web Token) is a signed string that carries claims like the user id and an expiry time. Because it is signed with a secret, the server can trust it without storing anything — it just checks the signature. The client sends it in an Authorization header as a 'bearer' token, meaning 'whoever bears this token is allowed in'. This is the go-to flow for APIs, single-page apps, and mobile apps.
export default {
async fetch(req, env) {
const header = req.headers.get("Authorization") || "";
const [scheme, token] = header.split(" ");
if (scheme !== "Bearer" || !token) {
return new Response("Missing bearer token", { status: 401 });
}
const valid = await verifyJWT(token, env.JWT_SECRET);
if (!valid) return new Response("Invalid token", { status: 401 });
return Response.json({ ok: true, message: "Welcome back!" });
}
};
// Verify an HS256 JWT signature with the Web Crypto API
async function verifyJWT(token, secret) {
const [head, body, sig] = token.split(".");
if (!head || !body || !sig) return false;
const key = await crypto.subtle.importKey(
"raw",
new TextEncoder().encode(secret),
{ name: "HMAC", hash: "SHA-256" },
false,
["verify"]
);
const signed = new TextEncoder().encode(head + "." + body);
const bytes = Uint8Array.from(
atob(sig.replace(/-/g, "+").replace(/_/g, "/")),
(c) => c.charCodeAt(0)
);
return crypto.subtle.verify("HMAC", key, bytes, signed);
}Verifying the signature is not enough
After the signature checks out, also decode the payload and reject the token if its exp (expiry) has passed. Keep tokens short-lived (minutes to an hour) and store the secret in a Worker secret, never in code.
4. OAuth third-party login
OAuth lets users log in with an account they already have, like Google or GitHub, without giving your app their password. Your app redirects the user to the provider, the user approves, and the provider redirects back with a short-lived code. Your app then swaps that code for an access token on the server side. The 'authorization code' style below is the secure, recommended pattern.
Code, not token, in the browser
The browser only ever sees a one-time code; the real token is fetched server-to-server so it never leaks. Keep the client secret on the server, and use a state value plus PKCE to block forged callbacks.
When to use each
Access SSO
Internal tools for your own team. No login code to write — Cloudflare guards the door and enforces who gets in.
Session cookie
Traditional, server-rendered websites where the browser is the only client. Simple to reason about and easy to revoke.
JWT bearer
APIs, single-page apps, mobile apps, and service-to-service calls. Stateless — no session store needed.
OAuth
Let users sign in with Google, GitHub, or similar — or access their data on those services with their permission.
Key terms
SSO
Single Sign-On: log in once, reach many apps without logging in again.
Session
The server's record of one logged-in visitor, usually kept in a store like KV.
Cookie
A small value the browser stores and resends on every request — here it carries the session id.
JWT
A signed JSON token holding claims (user id, expiry) that the server can trust without a lookup.
Bearer token
Sent as 'Authorization: Bearer <token>'. Whoever holds it is treated as authorized.
OAuth
A standard for logging in with another service's account without sharing your password.
Tips & gotchas
Always over HTTPS
Cookies and bearer tokens are like keys — anyone who copies them can impersonate the user. HTTPS keeps them from being read in transit, and is on by default for any Cloudflare-proxied domain.
- Never store a raw JWT or session id in localStorage if you can avoid it — an HttpOnly cookie is safer against XSS.
- Always verify a JWT's signature AND its expiry on the server; never trust the payload alone.
- For pure internal tools, Cloudflare Access often replaces all of this with zero auth code.
- Add Turnstile to your login form to block bots before they ever reach your password check.
- Give sessions and tokens a short lifetime, and provide a real logout that deletes the server-side session.
Related products
menu_bookOfficial docsopen_in_new