In short
Authentication (authN) answers "who are you?"; authorisation (authZ) answers "what are you allowed to do?". Web applications implement them with server-side sessions (state on the server, a session id in a cookie) or with tokens such as JWT (state carried in a signed token), and delegate identity to other providers using OAuth 2.0 and OpenID Connect (Login with Google, UPI/account-aggregator style consent flows). The topic appears in university papers on web technologies, information security and cryptography, in UGC-NET/GATE CS security questions, and in almost every placement interview for back-end, full-stack and cloud roles at TCS, Infosys, Wipro, Zoho, Freshworks, Razorpay, Zerodha, Paytm and product startups. It is also a compliance subject in India: the DPDP Act 2023, RBI's authentication and tokenisation directions, and CERT-In reporting rules all turn on how login and access control are built.
Explained
Authentication, authorisation and the related terms
- Identification - claiming an identity (typing a username). Authentication - proving it. Authorisation - deciding what that proven identity may do. Accounting/auditing - logging what it did. Together, "AAA".
- Authentication factors: (1) something you know - password, PIN; (2) something you have - phone, OTP, smart card, FIDO2 security key; (3) something you are - fingerprint, iris, face. MFA uses two or more *different* factors; password + security question is not MFA.
- Two-factor in India: the RBI mandates additional factor of authentication for most card-not-present transactions, and in banking the common factors are OTP on the registered mobile, UPI PIN, or device binding. Exact thresholds and exemptions (e-mandates, small-value contactless) have been revised several times, so quote the current RBI circular rather than a fixed figure.
- Authorisation models:
- ACL (access control list) - per-object list of who may do what.
- RBAC (role-based) - permissions attach to roles (admin, maker, checker, student, faculty); users get roles. The common industry default.
- ABAC (attribute-based) - rules over attributes:
dept == 'CSE' and time < 18:00 and device == managed. - MAC vs DAC - mandatory access control uses system-wide labels (Bell-LaPadula "no read up, no write down"); discretionary access control lets the owner grant access. Principle of least privilege and separation of duties apply to all of them.
- Statelessness problem: HTTP is stateless, so each request must carry proof of identity. Everything below is a way of carrying that proof.
Passwords: storage, hashing and policy
- Never store plaintext or reversibly encrypted passwords. Store
hash(salt + password)with a slow password hashing function. - Salt - a unique random value per user; defeats rainbow tables and makes two identical passwords hash differently. Pepper - a secret added from configuration, not stored with the hash.
- Use bcrypt, scrypt or Argon2id - designed to be slow and (scrypt/Argon2) memory-hard. Plain MD5/SHA-1/SHA-256 are far too fast for passwords (GPUs do billions of SHA-256 per second) though SHA-256 is fine inside HMAC and digital signatures.
- Work factor / cost: bcrypt's cost
cmeans 2c iterations; raising cost by 1 doubles the time. Tune so a verification takes roughly 50-250 ms on production hardware. - Defences: rate limiting and exponential backoff, account lockout (with care - it enables denial of service), CAPTCHA, breached-password checks, no "username not found" vs "wrong password" distinction (prevents user enumeration).
- Attacks to name: brute force, dictionary, credential stuffing (reused passwords from breaches), rainbow tables, phishing, keylogging, password spraying.
- Password reset must use a single-use, short-lived, high-entropy token sent out of band - not a security question alone.
Session-based authentication (stateful)
- User POSTs credentials over HTTPS; server verifies the password hash.
- Server creates a session record (user id, roles, created-at, IP/UA) in memory, Redis or a database, keyed by a cryptographically random session id (≥128 bits of entropy).
- Server returns
Set-Cookie: SID=...; HttpOnly; Secure; SameSite=Lax; Path=/. - Browser sends the cookie automatically on every same-site request; server looks the session up and loads the user.
- Logout, or expiry, deletes the server-side record - instant revocation.
- Cookie attributes:
HttpOnly(JavaScript cannot read it - blunts XSS theft),Secure(HTTPS only),SameSite=Strict/Lax/None(CSRF control;NonerequiresSecure),Domain/Path(scope),Max-Age/Expires(persistent vs session cookie). - Expiry types: *absolute* (fixed lifetime), *idle/sliding* (renewed on activity), *renewal* (rotate the id periodically).
- Session fixation - attacker plants a known session id before login; fix by regenerating the session id at login (and at privilege change).
- Session hijacking - stealing the id via XSS, network sniffing or logs; fix with HTTPS everywhere + HSTS, HttpOnly, short expiry, binding to user agent/IP (carefully - mobile IPs change).
- CSRF (cross-site request forgery) - because cookies are sent automatically, a third-party page can trigger a state-changing request. Fixes: synchroniser token (per-session random token in a hidden field, verified server-side), double-submit cookie,
SameSitecookies, and checkingOrigin/Referer. CSRF tokens must *not* beHttpOnly-inaccessible to the page's own JS if the JS must send them. - Scaling: sticky sessions, or shared session store (Redis/Memcached), or signed cookie-based sessions. Server-side store costs one lookup per request.
JWT and token-based authentication (stateless)
- A JWT is
base64url(header) . base64url(payload) . base64url(signature)- three dot-separated parts. It is signed, not encrypted: anyone can decode and read the payload. For confidentiality use JWE; the plain signed form is JWS. - Header:
{"alg":"HS256","typ":"JWT","kid":"key-1"}. Payload claims: registered -iss(issuer),sub(subject/user id),aud(audience),exp(expiry, seconds since epoch),nbf,iat,jti(unique id); plus private claims likeroles,tenant. - Signature algorithms:
HS256= HMAC-SHA256 with one shared secret (issuer and verifier both hold it);RS256/PS256= RSA signature andES256= ECDSA, where the issuer signs with a private key and any service verifies with the public key (published as a JWKS at/.well-known/jwks.json). Prefer asymmetric for multi-service systems. - Verification steps: check
algagainst an allow-list; verify the signature; checkexp/nbfwith small clock skew; checkissandaud; then apply authorisation from the claims. - Access token vs refresh token: a short-lived access token (5-15 min) is sent on every API call as
Authorization: Bearer <jwt>; a long-lived refresh token (days) is stored more carefully and exchanged at the token endpoint for a new access token. Refresh token rotation issues a new refresh token each time and detects reuse of an old one (replay) by revoking the family. - Revocation is the weak point: a stateless token stays valid until
exp. Mitigations - short expiry, a denylist ofjti, a per-usertoken_version/last_logout_atchecked on refresh, or short-lived tokens + server-side refresh records (semi-stateless). - Where to store a token in a browser:
localStorageis readable by any injected script (XSS risk); a cookie is sent automatically (CSRF risk, mitigated bySameSite+ CSRF token). Current guidance for browser apps is anHttpOnly,Secure,SameSitecookie, or keeping the access token in memory only with a cookie-bound refresh. For mobile and server-to-server clients, store in the OS keystore. - Classic JWT vulnerabilities:
alg: noneaccepted; algorithm confusion (RS256 token re-signed as HS256 using the public key as the HMAC secret); not verifying the signature at all ("decode" instead of "verify"); missingaudallowing a token for service A to be replayed at service B; weak HMAC secret; putting PII or secrets in the payload; trustingkidto fetch a key from an attacker-supplied URL. - Opaque vs JWT tokens: an opaque random string must be introspected at the issuer (stateful but revocable); a JWT is self-contained (fast but hard to revoke).
OAuth 2.0 and OpenID Connect
- OAuth 2.0 is delegated authorisation, not authentication. It lets a client app obtain limited access to a resource server on behalf of a resource owner (user), with tokens issued by an authorisation server. Think "let this app read my Google Drive files", not "prove who I am".
- Roles: resource owner, client (confidential - has a secret, e.g. a server app; or public - SPA, mobile), authorisation server, resource server. Scopes limit what the token can do (
read:profile,payments:write). - Grant types (flows):
- Authorisation Code + PKCE - the standard for web, SPA and mobile apps. Browser redirect → user consents → short-lived
codereturned to the redirect URI → client exchanges code (+code_verifier) for tokens at the token endpoint over the back channel. PKCE (code_challenge = BASE64URL(SHA256(code_verifier))) stops a stolen code being used by an attacker. - Client Credentials - machine-to-machine; no user involved.
- Refresh Token - exchange a refresh token for a new access token.
- Device Authorisation - input-constrained devices (smart TVs): show a code, user approves on a phone.
- Implicit and Resource Owner Password Credentials - legacy, now discouraged/removed in the OAuth 2.1 direction because tokens travelled in URL fragments and apps handled raw passwords.
- Authorisation Code + PKCE - the standard for web, SPA and mobile apps. Browser redirect → user consents → short-lived
- Security parameters:
state(CSRF protection on the redirect),nonce(replay protection for the ID token), exact-match registered redirect URIs, PKCE for all clients. - OpenID Connect (OIDC) sits on OAuth 2.0 and adds authentication: an ID token (always a JWT with
iss,sub,aud,exp,iat,nonce, plus profile claims), a/userinfoendpoint, standard scopesopenid profile email, and discovery at/.well-known/openid-configuration. Rule of thumb: ID token = who the user is (for the client); access token = what the client may call (for the API). - SSO and federation: OIDC and SAML 2.0 (XML assertions, used widely in enterprise and campus/academic federations) both give single sign-on; OIDC is JSON/REST and mobile-friendly, SAML is browser-POST and entrenched in legacy enterprise IdPs. LDAP/Active Directory and Kerberos (ticket-granting tickets, intranet SSO) are the on-premises classics.
- Indian identity rails: Aadhaar-based eKYC/OTP authentication through UIDAI (licensed AUA/KUA entities only, under the Aadhaar Act 2016 and its amendments), DigiLocker for issued documents, Account Aggregator consent artefacts under RBI for financial data sharing, and e-Sign/DSC under the Information Technology Act 2000 for digital signatures. The DPDP Act 2023 requires verifiable consent, purpose limitation and breach notification (from 13 May 2027 under the DPDP Rules 2025; until then IT Act s.43A and the SPDI Rules 2011 govern); CERT-In's 2022 directions require reporting specified incidents within six hours and retaining logs (commonly cited as 180 days) - check the current text before relying on exact timelines.
Authorisation design, API keys and transport security
- Where to enforce: always on the server. Hiding a button is UI, not authorisation. Check on *every* request, including the object id - omitting that is IDOR/BOLA (broken object-level authorisation), the top API risk:
GET /invoices/1043must verify the invoice belongs to the caller. - Patterns: middleware/guard per route, policy objects, scopes on tokens, row-level security in the database, API gateway doing coarse checks and the service doing fine-grained ones.
- API keys identify an application, not a user, and carry no expiry or scope by default - fine for server-to-server with IP allow-listing and rotation, not a substitute for user authN.
- Other schemes: HTTP Basic (base64 of
user:pass, no hashing - HTTPS only), Digest (obsolete), mTLS/client certificates (used in banking and UPI integrations), HMAC request signing (used by payment gateways and AWS SigV4 - signature over method, path, body and timestamp prevents tampering and replay). - Transport and headers: TLS 1.2/1.3 everywhere, HSTS, secure cookie flags, CORS configured with explicit origins (
Access-Control-Allow-Credentials: truecannot be combined with*), CSP to reduce XSS, and no tokens in URLs (they land in logs, history and Referer headers). - Passwordless and modern: magic links, OTP-only login (common in Indian consumer apps), WebAuthn/FIDO2 passkeys - public-key credentials bound to the origin, immune to phishing and credential stuffing; TOTP authenticator apps (RFC 6238) over SMS OTP where possible, since SMS is subject to SIM swap.
Key points
- Authentication vs authorisation - who you are vs what you may do; 401 Unauthorized means "not authenticated", 403 Forbidden means "authenticated but not allowed".
- Session - server keeps state, client holds only a random id in a cookie; easy revocation, needs a shared store to scale.
- JWT - self-contained signed claims, no server lookup; fast and scalable, but revocation and payload size are the costs.
- Signed ≠ encrypted - a JWT payload is base64url, readable by anyone; never put secrets or sensitive PII in it.
- Cookie flags -
HttpOnlyblunts XSS theft,Secureforces HTTPS,SameSiteblunts CSRF. - Session fixation fix - regenerate the session id immediately after a successful login.
- CSRF - exploits automatic cookie sending; fixed by synchroniser tokens plus
SameSite, not by HTTPS. - XSS - steals whatever the page's JavaScript can read; this is why
localStoragetoken storage is risky. - Password hashing - bcrypt/scrypt/Argon2id with a per-user salt; never MD5, SHA-1 or bare SHA-256.
- Access vs refresh token - short-lived bearer for API calls; long-lived, carefully stored token to mint new ones, with rotation and replay detection.
- OAuth 2.0 is authorisation; OIDC adds authentication via the ID token.
- Authorisation Code + PKCE is the correct flow for SPAs and mobile apps; implicit and password grants are deprecated.
- **
stateandnonce** - CSRF protection on the redirect, and replay protection for the ID token. - **JWKS and
kid** - public keys published for verification; allows key rotation without redeploying consumers. - Algorithm allow-list - reject
alg: noneand never let the token choose between HMAC and RSA verification. - RBAC vs ABAC - roles are simple and auditable; attributes express context-dependent rules.
- IDOR/BOLA - authorisation must be checked against the specific object, not just the route.
- MFA and passkeys - different factors; WebAuthn is phishing-resistant because the credential is origin-bound.
Formulas and examples
Time to brute force ≈ 2H−1 / R seconds - R = guesses per second the attacker achieves.
bcrypt work = 2c hash iterations (c = cost factor); doubling time per +1 of c.
Session id entropy ≥ 128 bits; collision risk follows the birthday bound ≈ n² / (2 × 2b) for n ids of b bits.
JWT size ≈ 1.37 × (bytes of header + payload + signature) because base64 expands data by 4/3 (plus 2 dots).
Access token lifetime T: expected worst-case misuse window after logout = T (stateless) vs ≈ 0 (server-side session).
HMAC-SHA256: tag = H((K ⊕ opad) ‖ H((K ⊕ ipad) ‖ M)) - K = secret key, M = message, ⊕ = XOR, ‖ = concatenation.
Example 1 - password entropy and cracking time. An 8-character password from lowercase + uppercase + digits: N = 26+26+10 = 62, L = 8.
- log₂62 ≈ 5.954, so H ≈ 8 × 5.954 ≈ 47.6 bits; search space 62⁸ ≈ 2.18 × 10¹⁴.
- Against SHA-256 at R = 10¹⁰ guesses/s (a GPU rig): average time ≈ (2.18 × 10¹⁴ / 2) / 10¹⁰ ≈ 1.09 × 10⁴ s ≈ 3.0 hours.
- Against bcrypt tuned to 100 ms per verify, a single machine does R = 10/s: ≈ (1.09 × 10¹⁴)/10 ≈ 1.09 × 10¹³ s ≈ 346,000 years.
- Same password, slow hash - the hash choice, not the password, changed the outcome by ~9 orders of magnitude (the ratio of the two guess rates, 10¹⁰ vs 10).
Example 2 - bcrypt cost tuning. A server verifies a bcrypt hash at cost 10 in 60 ms.
- Cost 12 = 2² = 4× the work → 60 × 4 = 240 ms; cost 14 → 60 × 16 = 960 ms (too slow for a login API).
- At 240 ms per verify, one CPU core sustains 1/0.24 ≈ 4.2 logins/s; to serve a 500-logins/s peak you need ≈ 500/4.2 ≈ 120 cores of hashing capacity. Choose cost 11 (120 ms, 8.3 logins/s/core) or add a login queue - the exam point is that password hashing cost is a capacity decision.
Example 3 - session store vs JWT at scale. An API serves 20,000 requests/s; 80,000 users are logged in; each session record is 500 bytes.
- Sessions: 20,000 Redis GETs/s (well within one Redis node); memory = 80,000 × 500 B = 40 MB; logout takes effect immediately.
- JWT (HS256, 600-byte token): zero lookups, but 12 MB/s of extra inbound header traffic (20,000 × 600 B) ≈ 1.04 TB/day, and with
exp= 15 min a revoked user keeps access for up to 900 s. - Verdict: sessions for a single-origin app needing instant logout; JWT when many independent services must verify without calling an auth service.
Example 4 - JWT expiry arithmetic and skew. A token has iat = 1,756,000,000 and exp = 1,756,000,900.
- Lifetime = 900 s = 15 minutes. A verifier whose clock is 120 s *ahead* sees "now" = 1,756,000,920 >
expand rejects a still-valid token unless a leeway (typically 30-60 s) is allowed - hence NTP-synced clocks and a small configured skew. - With refresh-token rotation at 15-minute intervals over an 8-hour workday: 8 × 60 / 15 = 32 access tokens issued, so an attacker who steals one access token has at most 15 minutes, while a stolen refresh token is caught at the next legitimate rotation (reuse detection).
Example 5 - Authorisation Code + PKCE, step by step. A React SPA at https://app.example.in logs a user in via an OIDC provider.
- SPA generates
code_verifier(43-128 random chars) andcode_challenge = base64url(SHA256(verifier)), plus randomstateandnonce. - Redirect to
/authorize?response_type=code&client_id=spa1&redirect_uri=https://app.example.in/cb&scope=openid%20profile&state=xyz&nonce=abc&code_challenge=...&code_challenge_method=S256. - User authenticates and consents at the provider; browser returns to
/cb?code=AX7...&state=xyz. SPA **verifiesstatematches**. - SPA POSTs to
/tokenwithcode,code_verifier,client_id(no client secret - public client). Provider recomputes SHA256(verifier) and compares with the stored challenge. - Response:
{access_token, id_token, refresh_token, token_type:"Bearer", expires_in:900}. SPA verifies the ID token signature via JWKS and checksiss,aud,exp,nonce. - API calls carry
Authorization: Bearer <access_token>; the API verifies signature,aud,expand scopes - then checks object ownership.
// Express: session login vs JWT verify (illustrative)
app.post('/login', async (req, res) => {
const u = await db.user(req.body.email);
if (!u || !await bcrypt.compare(req.body.password, u.hash))
return res.status(401).json({error: 'invalid credentials'}); // same message both cases
req.session.regenerate(() => { // prevents session fixation
req.session.uid = u.id; req.session.roles = u.roles;
res.json({ok: true});
});
});
function auth(req, res, next) {
const t = (req.headers.authorization || '').replace('Bearer ', '');
try {
req.user = jwt.verify(t, PUBLIC_KEY, {
algorithms: ['RS256'], // allow-list: blocks alg:none and HS/RS confusion
issuer: 'https://id.example.in', audience: 'jobs-api', clockTolerance: 30
});
next();
} catch (e) { res.status(401).json({error: 'invalid token'}); }
}
const needRole = r => (req, res, next) =>
req.user.roles.includes(r) ? next() : res.status(403).json({error: 'forbidden'});
| Aspect | Server-side session | JWT (stateless) |
|---|---|---|
| State | On server (Redis/DB) | In the token |
| Lookup per request | Yes (1 read) | No (verify signature) |
| Revocation | Immediate on delete | Only at exp, or needs a denylist |
| Payload visibility | Nothing exposed | Claims readable by anyone |
| Horizontal scaling | Shared store or sticky sessions | Trivially scalable |
| Cross-domain / microservices | Awkward | Natural |
| Main risk | Hijacking, fixation, CSRF | Theft via XSS, weak keys, no revocation |
| Typical size on wire | ~32-64 byte cookie | ~300-1,000 bytes per request |
| Artefact | Issued by | Audience | Purpose | Typical life |
|---|---|---|---|---|
| Session id | App server | App server | Look up server-side session | Minutes to weeks (idle timeout) |
| Access token | Authorisation server | Resource server (API) | Authorise API calls | 5-15 minutes |
| Refresh token | Authorisation server | Authorisation server | Mint new access tokens | Hours to months, rotated |
| ID token (OIDC) | Identity provider | Client app | Convey user identity | Minutes; used once at login |
| API key | Service provider | Service provider | Identify a calling application | Until rotated |
Where it is used
- Fintech and banking: RBI-mandated additional-factor authentication, UPI PIN flows, mTLS and HMAC-signed webhooks at Razorpay/PayU/Cashfree, card tokenisation replacing stored card numbers, maker-checker RBAC in core banking and loan origination systems.
- Government and public digital infrastructure: Aadhaar OTP/eKYC via licensed AUA/KUA entities, DigiLocker document fetch with user consent, e-Sign, SSO on tax, GST, EPFO and university portals, Account Aggregator consent artefacts.
- SaaS and enterprise IT: SAML/OIDC single sign-on into Zoho, Freshworks, Darwinbox and Microsoft Entra ID; SCIM provisioning; AWS IAM roles, policies and STS temporary credentials; Kubernetes service accounts and RBAC.
- Consumer apps and job roles: OTP-first login in Indian consumer apps (Swiggy, Flipkart, Ola), Login-with-Google in SPAs; the work sits with back-end/full-stack engineers, API/platform engineers, DevOps and cloud engineers, and is tested by security analysts and VAPT teams against the OWASP Top 10 and API Top 10.
- Campus and academic systems: institutional LDAP/Active Directory logins, NPTEL/SWAYAM and library federations, examination portals using role-based access for student, faculty and controller-of-examinations roles.
- Compliance and audit: DPDP Act 2023 consent and breach duties, CERT-In incident reporting and log retention, ISO/IEC 27001 access-control controls - all of which ask for evidence of how authentication and authorisation are implemented and logged.
Interview questions
- Q: Difference between authentication and authorisation, with the HTTP status codes? A: Authentication verifies identity (failure → 401 with a
WWW-Authenticatechallenge); authorisation decides permissions for an already-identified user (failure → 403). - Q: Is a JWT encrypted? A: No - a standard JWS is signed and base64url-encoded, so anyone can read the claims; use JWE or simply keep sensitive data out of the payload.
- Q: How do you revoke a JWT before it expires? A: You cannot by signature alone - use short expiry plus a refresh flow, a
jtidenylist in Redis, or a per-user token version/last_logout_atchecked at refresh time. - Q: Where should a browser SPA store its tokens? A: Preferably an
HttpOnly,Secure,SameSitecookie (with CSRF protection), or the access token in memory with a cookie-bound refresh token;localStorageexposes it to any XSS. - Q: What is session fixation and how is it prevented? A: An attacker gets the victim to use a session id the attacker already knows; prevent it by regenerating the session id on successful login and on privilege change.
- Q: Why does
SameSitehelp with CSRF but not XSS? A:SameSitestops the browser attaching cookies to cross-site requests, while XSS runs inside your own origin, where cookies are sent legitimately. - Q: What problem does PKCE solve? A: It binds the authorisation code to the client that started the flow, so a code intercepted on a mobile redirect or in browser history cannot be exchanged without the original
code_verifier. - Q: OAuth 2.0 vs OpenID Connect? A: OAuth 2.0 delegates authorisation (access tokens with scopes); OIDC is a profile on top that adds authentication via a signed ID token,
/userinfoand discovery. - Q: HS256 vs RS256 - which for microservices and why? A: RS256: the issuer holds the private key and every service verifies with a published public key, so no shared secret is distributed and keys can be rotated via JWKS.
- Q: What is the algorithm-confusion attack? A: Taking an RS256 token, switching
algto HS256 and signing with the public key as the HMAC secret; defeated by verifying against an explicit algorithm allow-list. - Q: Why bcrypt and not SHA-256 for passwords? A: SHA-256 is designed to be fast, so GPUs test billions per second; bcrypt/Argon2 have a tunable cost (and memory hardness) that makes each guess expensive.
- Q: What is IDOR and how do you prevent it? A: Accessing another user's object by changing an id in the request; prevent it by checking ownership/permission for the specific object server-side, never relying on unguessable ids alone.
- Q: Why is TOTP preferred over SMS OTP? A: TOTP is generated locally from a shared secret and a time counter, so it is not exposed to SIM-swap, SS7 interception or delivery failure - though SMS remains common in India for reach.
Common mistakes
- Saying "JWT is more secure than sessions" - they trade revocation and simplicity for statelessness; neither is inherently more secure.
- Decoding a JWT instead of verifying it, or accepting whatever
algthe token names (includingnone). - Storing passwords with MD5/SHA-1, or hashing without a per-user salt, or inventing a custom hash scheme.
- Enforcing authorisation only in the UI or at the route level, and forgetting the object-level check (IDOR/BOLA).
- Confusing XSS with CSRF, and claiming HTTPS or
HttpOnlyalone stops CSRF. - Forgetting to regenerate the session id at login, or to actually delete the server-side record on logout (clearing the cookie is not logout).
- Treating OAuth 2.0 as a login protocol - using an access token as proof of identity instead of an OIDC ID token, or trusting unverified
/userinfofields. - Putting tokens in query strings, logging
Authorizationheaders, or using long-lived access tokens with no refresh and no expiry.
Related topics
REST APIs · Back-end development with Node.js · Cloud computing basics · AWS core services · Cryptography: hashing, symmetric and public-key · Network and web security: OWASP Top 10, TLS