System-design · Authentication

Authentication Interview Questions
With Answers & Code Examples

6 carefully curated Authentication interview questions with working code examples and real interview gotchas.

Practice Interactively →← All Categories
6 questions2 beginner3 core1 advanced
Q1Beginner

What are the security differences between storing a JWT in localStorage vs an HttpOnly cookie?

💡 Hint: localStorage is XSS-vulnerable; HttpOnly cookies are inaccessible to JS but need CSRF protection

localStorage

  • Accessible via JavaScript — any XSS vulnerability can steal the token: document.cookie — wait, actually localStorage.getItem('token').
  • Token theft = account takeover. Attacker can make authenticated API calls from anywhere.
  • Not automatically sent to the server — must manually attach: Authorization: Bearer <token>.

HttpOnly cookie

  • HttpOnly flag prevents JavaScript from reading the cookie — XSS cannot steal it.
  • Secure flag ensures it only travels over HTTPS.
  • SameSite=Strict/Lax prevents CSRF — cookie not sent on cross-origin requests.
  • Automatically included by the browser on every same-origin request — no manual header attachment.
Set-Cookie: token=<jwt>; HttpOnly; Secure; SameSite=Strict; Path=/

Verdict: HttpOnly cookies are strictly more secure. The main downside is CSRF risk (mitigated by SameSite) and that the token is sent on every request (including non-API routes) — use a short Path to scope it.

Practice this question →
Q2Core

What is refresh token rotation and why is it important?

💡 Hint: Each refresh issues a new refresh token and invalidates the old one — if a stolen token is used, the legitimate session is detectable

The problem: Access tokens are short-lived (15 min), but refresh tokens are long-lived (days/weeks). A stolen refresh token gives an attacker indefinite access.

Refresh token rotation:

  1. When a client uses a refresh token to get a new access token, the server issues a brand-new refresh token and invalidates the old one.
  2. If an attacker steals the refresh token and tries to use it after the legitimate client already rotated it, the server detects the reuse of an already-invalidated token.
  3. Server policy on reuse detection: invalidate the entire refresh token family (all sessions) — forces re-authentication.
// Token family concept
POST /auth/refresh { refreshToken: "rt_v1" }
→ { accessToken: "at_new", refreshToken: "rt_v2" }
// rt_v1 is now invalid

// If attacker uses rt_v1 again:
POST /auth/refresh { refreshToken: "rt_v1" }
→ 401 — AND server invalidates rt_v2 too (reuse detected)

Storage: Refresh tokens should be stored in HttpOnly cookies, never localStorage.

Practice this question →
Q3Core

What is OAuth 2.0 PKCE and when should you use it?

💡 Hint: PKCE replaces the client secret for public clients (SPAs, mobile apps) — proves the token recipient is the same app that started the flow

PKCE (Proof Key for Code Exchange, pronounced "pixie") is an OAuth 2.0 extension that protects the authorization code flow for public clients (SPAs, mobile apps) that can't securely store a client secret.

The problem with SPAs: A client secret embedded in a SPA's JavaScript bundle is public — anyone can extract it and impersonate your app.

How PKCE works:

  1. App generates a random code verifier (43–128 chars) and computes its SHA-256 hash → code challenge.
  2. Authorization request includes the code challenge.
  3. Auth server stores the code challenge alongside the issued authorization code.
  4. Token exchange request includes the original code verifier.
  5. Auth server hashes the verifier and compares to stored challenge — only the original app can match.
// Step 1: generate
const codeVerifier = generateRandomString(64);
const codeChallenge = base64urlEncode(sha256(codeVerifier));

// Step 2: redirect with challenge
window.location.href = `${authServer}/authorize?
  code_challenge=${codeChallenge}&code_challenge_method=S256&...`;

Use PKCE for: all SPAs, mobile apps, any public client. It's now recommended even for confidential clients.

Practice this question →
Q4Beginner

What is the difference between authentication and authorization?

💡 Hint: Authentication = who are you (identity); authorization = what are you allowed to do (permissions)

Authentication (AuthN) — verifying identity. "Who are you?"

  • Mechanisms: password, OAuth, SAML, biometrics, passkeys.
  • Output: a verified identity (user ID, claims in a JWT, session record).
  • Example: checking that a submitted password matches the stored hash.

Authorization (AuthZ) — determining permissions. "What are you allowed to do?"

  • Mechanisms: RBAC (Role-Based), ABAC (Attribute-Based), ACLs, scopes in OAuth tokens.
  • Input: the verified identity from authentication.
  • Example: checking that the authenticated user has the admin role before showing /admin.

On the frontend:

// Authentication check — are you logged in?
if (!user) return <Redirect to="/login" />;

// Authorization check — do you have permission?
if (!user.roles.includes('admin')) return <Forbidden />;

Key rule: never rely on frontend-only authorization checks for security. The server must enforce permissions on every request. Frontend checks are UX, not security.

Practice this question →
Q5Core

What is SSO (Single Sign-On) and how is it implemented on the frontend?

💡 Hint: One login grants access to multiple apps — implemented via a shared identity provider using SAML or OIDC/OAuth 2.0 redirects

SSO lets a user log in once to an identity provider (IdP) and gain access to multiple service providers (SPs) without logging in again.

Common protocols:

  • SAML 2.0 — XML-based, enterprise standard (Okta, Active Directory). Browser-redirect flow. Rarely implemented directly by frontend engineers.
  • OpenID Connect (OIDC) — built on OAuth 2.0, returns a JWT ID token. The modern standard for SPAs and mobile apps.

Frontend OIDC flow (PKCE):

  1. User clicks "Login" → app redirects to IdP (/authorize).
  2. IdP authenticates the user, redirects back with an authorization code.
  3. App exchanges the code for ID + access tokens.
  4. App stores tokens (HttpOnly cookie or memory); uses access token for API calls.

Session sharing across apps: The IdP maintains the SSO session (usually via its own cookie). When app B redirects to the IdP, it detects the existing session and redirects straight back without showing the login form.

Practice this question →
Q6Advanced

How would you implement silent token refresh in a SPA?

💡 Hint: Use a hidden iframe to hit the IdP (if SSO session exists) or an in-memory refresh token to get a new access token before expiry

Access tokens expire (typically 15 min). Silent refresh keeps users logged in without forcing them to re-authenticate.

Option 1: Hidden iframe (OIDC prompt=none)

// When access token is near expiry, load IdP in hidden iframe
const iframe = document.createElement('iframe');
iframe.src = `${idpUrl}/authorize?prompt=none&response_type=code&...`;
iframe.style.display = 'none';
document.body.appendChild(iframe);
// Listen for redirect back to /silent-callback
// Parse new token from callback URL

Works if the user still has an active SSO session with the IdP. Requires prompt=none OIDC parameter. Blocked by Safari ITP (third-party cookie restrictions).

Option 2: Refresh token in HttpOnly cookie

// Before request, check token expiry
async function getAccessToken() {
  if (isExpiringSoon(accessToken)) {
    const { data } = await axios.post('/auth/refresh'); // sends HttpOnly cookie automatically
    accessToken = data.accessToken; // store in memory only
  }
  return accessToken;
}

Keep the access token in memory (not localStorage) to prevent XSS theft. The refresh token in HttpOnly cookie is safe from JavaScript. This is the recommended modern approach.

Practice this question →

Other System-design Interview Topics

Rendering StrategiesCore JSType SystemReact FundamentalsFunctionsMicrofrontendsGenericsAsync JSHooksObjectsMonorepoArrays'this' KeywordUtility TypesError HandlingModern JSBundle OptimizationPerformanceDOM & EventsState ManagementClasses & OOPCaching StrategiesComponent PatternsAdvanced TypesReact RouterFormsAdvanced PatternsFrontend SecurityConcurrent ReactServer ComponentsTestingEcosystemNetwork OptimizationCore Web VitalsBrowser APIs

Ready to practice Authentication?

Get AI feedback on your answers, predict code output, and fix real bugs.

Start Free Practice →