"Why does the authorization code flow bother with a code at all?" the interviewer asked. "Why not just return the token?" The candidate said it was more secure, which is true and is not an answer. The actual answer is that the code travels through the browser's URL — where it lands in history, logs and referrer headers — and is useless without a secret the browser never sees.
OAuth 2.0 interview questions reward people who understand why each step exists, because almost every step is defending against a specific attack. Candidates who can recite the flow but not defend it get exposed immediately. This guide covers the roles, the flows that still matter, PKCE, OIDC, scopes and token handling.
What OAuth interviews actually test
OAuth interview questions appear in backend, full-stack, platform and security loops. Five bands:
- The mental model — the four roles, and what problem OAuth actually solves.
- The flows — authorization code, client credentials, and why implicit and password grants are deprecated.
- PKCE — what attack it prevents, and why it is now recommended for every client.
- OAuth vs OIDC — authorization vs authentication, the single most-asked conceptual question.
- Practicalities — scopes, token storage, refresh, the
stateparameter, redirect URI validation.
The mental model: four roles, one problem
Start with the problem OAuth solves, because it frames everything: letting an application access resources on your behalf without giving it your password. Before OAuth, the pattern was handing over your credentials, which gave unlimited, unrevocable, unscoped access.
The four roles:
- Resource owner — the user who owns the data.
- Client — the application requesting access.
- Authorization server — issues tokens after the user consents (Google, Okta, your own identity service).
- Resource server — the API holding the data and accepting the token.
The key distinction that follows, and interviewers check it: a confidential client can keep a secret (a backend server), while a public client cannot (a single-page app or mobile app, where anything shipped to the device is readable). Which flow you choose is largely determined by that one property.
The authorization code flow, and why the code exists
The flow that matters, step by step: the client redirects the user to the authorization server with its client ID, requested scopes, redirect URI and a state value; the user authenticates and consents; the authorization server redirects back with a short-lived authorization code; the client's backend exchanges that code, plus its client secret, for an access token over a direct server-to-server call.
Now the intro's question. The code exists because the browser redirect is a hostile channel — URLs end up in browser history, server logs, proxy logs and Referer headers. A code captured from there is useless without the client secret, and the token itself never touches the browser's address bar. That is the entire design rationale, and being able to state it is worth more than reciting the sequence.
The other parameters carry weight too:
state— a random value the client generates and verifies on return. It prevents CSRF on the redirect, where an attacker tricks your browser into completing a flow with their authorization code, silently linking your session to their account.- Redirect URI — must be pre-registered and matched exactly by the authorization server. Loose matching (wildcards, prefix matching) is a classic vulnerability that lets an attacker redirect the code to a site they control.
- Short code lifetime and single use — codes expire in seconds to a minute and must be redeemable once.
PKCE and the death of the implicit flow
The implicit flow returned an access token directly in the URL fragment, and existed because browsers once could not make cross-origin requests to a token endpoint. It is now deprecated: tokens leak through history and referrers, there is no client authentication, and refresh tokens cannot be issued safely. If asked whether to use it, the answer is no, and the reason is token exposure in the URL.
It was replaced by the authorization code flow with PKCE (Proof Key for Code Exchange), which lets public clients use the code flow safely:
- The client generates a random code verifier and sends its SHA-256 hash — the code challenge — with the authorization request.
- The authorization server stores the challenge alongside the issued code.
- When exchanging the code, the client sends the original verifier. The server hashes it and compares.
// Browser-side PKCE: generate the verifier, send only its hash
function base64url(bytes) {
return btoa(String.fromCharCode(...new Uint8Array(bytes)))
.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}
async function startLogin() {
const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
const challenge = base64url(digest);
// The verifier NEVER leaves the client until the code exchange
sessionStorage.setItem("pkce_verifier", verifier);
const state = base64url(crypto.getRandomValues(new Uint8Array(16)));
sessionStorage.setItem("oauth_state", state);
location.href = authorizeUrl + "?" + new URLSearchParams({
response_type: "code",
client_id: clientId,
redirect_uri: redirectUri,
scope: "openid profile",
state,
code_challenge: challenge,
code_challenge_method: "S256", // never "plain"
});
}
Note code_challenge_method: "S256". The spec permits plain, where the challenge is the verifier itself — which defeats the entire mechanism if the authorization request is intercepted. Interviewers sometimes ask why plain exists; the answer is legacy device compatibility, and you should never use it.
The attack this prevents is worth naming precisely: on mobile, a malicious app could register the same custom URL scheme as a legitimate app and intercept the redirect, stealing the code. Without a client secret (which a public client cannot keep), the attacker could redeem it. With PKCE, the attacker lacks the verifier, so the stolen code is worthless. Current guidance is to use PKCE for all clients including confidential ones — saying that shows you are current.
Also know that the resource owner password credentials grant is deprecated for the obvious reason: the app handles the user's password, which is exactly what OAuth was created to avoid. And client credentials remains fully valid — it is machine-to-machine, with no user involved, which is what you use for service-to-service calls.
OAuth vs OIDC: the most-asked question
State it in one line: OAuth 2.0 is authorization, OpenID Connect is authentication. OAuth answers "is this application allowed to do X on this user's behalf?" It never defines who the user is.
The consequence, and the reason this matters practically: using a bare OAuth access token to log someone in is insecure, because a token issued to a different application for the same user could be replayed at yours. OIDC layers on top of OAuth and adds:
- An ID token — a JWT describing the authenticated user, with an
audclaim naming your client, which is what defeats the replay above. - The
openidscope as the trigger, plus standard claims and a/userinfoendpoint. - A discovery document at a well-known URL so clients can configure themselves.
So "Sign in with Google" is OIDC; "let this app read your Google Drive files" is OAuth. Explaining that the ID token is for your client and the access token is for the API — and validating the ID token's signature, issuer, audience and expiry — is the complete answer. Our JWT interview questions guide covers the token format itself.
Scopes, tokens and the practical questions
- Scopes — coarse-grained permission labels requested by the client and consented to by the user (
read:contacts). Follow least privilege, and know that scopes are not a substitute for server-side authorization: the resource server must still check that this user may access this specific record. - Access token lifetime — short, because they cannot be revoked cheaply. Refresh tokens carry the long-lived state, with rotation for public clients.
- Token validation — either a locally verified JWT (fast, but revocation lags) or introspection against the authorization server (authoritative, adds a network call). Being able to argue both ways is the senior answer.
- Where tokens go in a SPA — the current recommendation is increasingly a backend-for-frontend that holds tokens server-side and gives the browser a session cookie, precisely because browser storage is exposed to XSS.
- Consent and revocation — users can withdraw access at the authorization server, which is a genuine advantage over shared passwords and worth mentioning.
The RFCs, OWASP, provider docs, ChatGPT — where each fits
- OAuth 2.0 Security Best Current Practice — the document that explains why implicit is dead and PKCE is universal. Short and directly interview-relevant.
- RFC 6749 and RFC 7636 — the core spec and PKCE. Dense, but the flow diagrams are what interviewers draw.
- Google, Auth0 and Okta developer docs — the clearest practical walkthroughs, with real parameter names.
- Implementing a login once yourself — highest yield. Wire up Sign in with Google end to end and watch the code appear in the URL bar; the design rationale becomes obvious.
- OWASP — for redirect URI validation and the
stateparameter attacks. - ChatGPT — good for explaining the flows and generating client code. It will not ask why the code exists instead of the token.
- Greenroom — the spoken layer. Ari, the AI interviewer, runs the round out loud and pushes the "why does that step exist?" follow-up. Fair tradeoff: Ari will not review your redirect URI configuration.
state stops CSRF, PKCE stops code interception. Learn the attacks and the flow becomes impossible to forget.How to prepare for an OAuth interview
- Week 1: the model and the code flow. Draw it from memory and narrate what each parameter defends against.
- Week 2: PKCE and deprecated flows. Be able to explain the mobile code-interception attack precisely, and why implicit and password grants are gone.
- Week 3: OIDC. Implement Sign in with Google, validate the ID token's signature, issuer, audience and expiry, and articulate authorization versus authentication in one sentence.
- Final week: practicalities — scopes, token lifetimes, introspection versus local validation, BFF for SPAs — then two full spoken mocks.
Building the rest of the stack? The JWT interview questions guide covers the token format, the API security guide covers the wider surface, and the system design guide covers where identity sits in an architecture.
Frequently asked questions
What are the most common OAuth interview questions?
The most common questions cover the four OAuth roles and the problem OAuth solves, the authorization code flow step by step and why an intermediate code exists rather than returning a token directly, what PKCE prevents and why it is now recommended for all clients, why the implicit and password grants are deprecated, the difference between OAuth and OpenID Connect, and what the state parameter defends against.
What is the difference between OAuth 2.0 and OpenID Connect?
OAuth 2.0 is an authorization framework that answers whether an application may act on a user's behalf, and it never defines who the user is. OpenID Connect is an authentication layer built on top of OAuth that adds an ID token — a JWT describing the authenticated user with an audience claim naming your client — plus the openid scope, standard claims, a userinfo endpoint and a discovery document. Signing users in with a bare OAuth access token is insecure.
Why does the authorization code flow use a code instead of returning a token?
Because the redirect back to the client travels through the browser, and URLs end up in browser history, server and proxy logs, and Referer headers. An authorization code captured from any of those is useless without the client secret, and the exchange happens over a direct server-to-server call so the access token never appears in the address bar. Codes are also short-lived and single-use, which further limits the window.
What is PKCE and what attack does it prevent?
PKCE, Proof Key for Code Exchange, has the client generate a random code verifier and send its SHA-256 hash as a code challenge with the authorization request, then present the original verifier when exchanging the code. It prevents authorization code interception, most notably on mobile where a malicious app can register the same custom URL scheme and capture the redirect. Without the verifier a stolen code cannot be redeemed. Current guidance recommends PKCE for all clients.
Why is the implicit flow deprecated?
The implicit flow returned an access token directly in the URL fragment, so tokens leaked into browser history, logs and referrer headers. It also provided no client authentication and could not safely issue refresh tokens. It existed only because browsers once could not make cross-origin requests to a token endpoint, which is no longer a constraint. It has been replaced by the authorization code flow with PKCE.
What does the state parameter do in OAuth?
The state parameter is a random value the client generates before redirecting and verifies when the user returns. It prevents cross-site request forgery on the redirect, where an attacker tricks a victim's browser into completing an authorization flow using the attacker's own code, which would silently link the victim's session to the attacker's account. It can also carry application context such as the page the user started from.