In this article
  1. Before you start
  2. Why interviewers ask this
  3. OAuth from first principles
  4. Worked example
  5. Trade-offs and edge cases
  6. How to answer it in an interview
  7. Common mistakes
  8. Follow-up questions
  9. Sources

Before you start

This page belongs to the distributed systems interview guide, where authentication and authorization come up in almost every design.

Why interviewers ask this

OAuth shows up whenever a design lets one product act on another's data: "sign in with a partner", a calendar integration, a payment connection, or a public API with third-party developers. Interviewers use it to see whether you can separate three ideas that sound alike: who the user is, what an app may do, and how a secret travels safely.

A weak answer says "OAuth is how you log in with Google." A strong answer names the four parties, walks the redirect-and-code sequence, and says why a code is exchanged for a token rather than a token being handed over directly. A Staff-level answer adds the failure modes: leaked tokens, forged redirects, and the short lifespan that limits both. The same ideas matter in an API design round and in a payment system design, where a connected account must be limited to exactly what the user approved.

OAuth from first principles

OAuth
OAuth is an authorization framework that lets an app obtain limited access to a service's protected data, either on behalf of a user who approves it or on its own behalf, by presenting a token issued by the service instead of the user's password.
Access token
An access token is a credential that an authorization server issues to an app so the app can call a protected API with limited rights. It stands in for the user's password, and the API accepts it for as long as it is valid.
Authorization code
An authorization code is a short-lived, single-purpose value that the authorization server returns through the user's browser after the user approves, and that the app then trades for an access token on a direct call.
PKCE
Proof Key for Code Exchange (PKCE) is an extension to the code flow in which the app invents a secret for each request, sends only its hash at the start, and reveals the secret when it redeems the code, so a stolen code is useless.

In plain words

Think of a hotel valet. You do not hand over your whole key ring. You hand over a valet key, which starts the car but cannot open the trunk or the glovebox. You approved that limited access yourself, and the valet never got your full set of keys.

The analogy breaks in one place. A physical key is hard to copy, but a token is only text, and anyone who holds a copy can use it. That is why tokens are kept short-lived and sent only over encrypted connections.

In one precise sentence: the Request for Comments (RFC) document RFC 6749 lets a client obtain limited access to an HTTP service, either on behalf of a resource owner after an approval step or on its own behalf. The same document names the four roles: the resource owner (the user), the client (the app), the authorization server (which issues tokens) and the resource server (the API). The current version, OAuth 2.0, defined in RFC 6749 (October 2012), replaced OAuth 1.0, which signed each request.

Step 1: The app sends the user to the authorization server with a state value

The client starts by redirecting the user's browser to the authorization server. The request carries the client's identifier, the redirect uniform resource identifier (URI) where the answer should come back, the requested scope, a state value and the PKCE challenge (RFC 7636).

A scope is a named permission, such as read-only access to a calendar, that the app asks for and the user approves. The state is a random value the app generates, stores in the user's session and expects back unchanged. If the returned value does not match, the app discards the response. That check blocks cross-site request forgery (CSRF), where an attacker feeds the app a code from the attacker's own session.

RFC 9700 says clients must send a one-time state value bound to the user's browser, or rely on PKCE once they have confirmed the server supports it. The challenge is a hash of a secret the app keeps until Step 3.

You now know what leaves the app.

Step 2: The user approves and the code returns with the same state

The authorization server asks the user to sign in, by whatever method it uses, and then shows a consent screen listing the requested scopes. OAuth does not define how the user proves who they are; that part belongs to the server.

On approval the server redirects the browser to the redirect URI with two query values: a short-lived authorization code and the state the app sent. The app first compares the state with the value it stored. A mismatch ends the flow.

The server must also check the redirect URI. RFC 9700 requires exact string matching against pre-registered addresses (with a narrow exception for the port of local addresses used by native apps), because a loose match lets an attacker steer the code to a site they control.

Input: the user's approval. Output: a code in the browser's address bar. Nothing yet lets the app call the API, and that is deliberate: the browser is the least trusted place in the flow.

Step 3: The app trades the code for a token, proving it started the request

The app now makes a direct call, with no browser in between, to the authorization server's token endpoint. It sends the code, its client identifier, the same redirect URI and the original PKCE secret, called the code_verifier. A confidential client, one that can keep a secret such as a server-side app, also authenticates, for example with its client secret (RFC 6749, §4.1.3); a public client has no secret and relies on PKCE.

The server hashes the verifier with the method named S256 and compares the result with the code_challenge it saw in Step 1 (RFC 7636). A match proves that the app redeeming the code is the app that started the request. An attacker who intercepted the code may have seen the challenge but not the verifier behind it.

On success the server returns an access token and, often, a refresh token. A refresh token is a longer-lived credential that lets the app get a new access token without asking the user again.

Input: code plus verifier. Output: an access token.

Step 4: The app calls the API with the access token

The app sends the access token in an Authorization: Bearer header on each API request. The resource server checks that the token is valid and unexpired, and that its scope allows the call, then returns the data.

"Bearer" means that whoever holds the token can use it, with no further proof. So tokens travel only over Transport Layer Security (TLS), the encryption behind Hypertext Transfer Protocol Secure (HTTPS), and stay short-lived. A short lifespan only limits the damage; RFC 9700 recommends sender-constrained tokens, bound to a key the client holds, as the stronger fix.

The framework does not fix the token's format. It can be a random string that the resource server looks up, or a signed JavaScript Object Notation (JSON) Web Token (JWT) that the server can check without a lookup. When the access token expires, the app presents its refresh token to the token endpoint and receives a new one.

Input: the token. Output: the data the user approved, and nothing beyond that scope. Every step of the flow, from request to API call, is now covered.

The code flow swaps a browser code for a tokenSequence of the OAuth code flow: the app redirects the user's browser to the authorization server, the user approves and a code returns through the browser, the app trades the code and verifier for an access token on a direct call, and then calls the API.App (client)UserbrowserAuthorization serverResourceserverredirect: state, scopeauthorization requestsigns in, approvescode, state via browserdirect call (back channel)access tokenbearer tokendataDiagram: Interview Clozo, CC BY 4.0 ·interview.clozo.ai/blog/oauth.html

The browser carries only a short-lived code; the token travels on a direct call between the app and the authorization server.CC BY 4.0 — source: What is OAuth, and how does the code flow work?
Step-by-step description
  1. The app redirects the browser with scope, state and challenge.
  2. The user approves and a code returns by redirect.
  3. Direct call: code plus verifier buys a token.
  4. The token opens the API.
  • The app sends a scope, a state value and a PKCE challenge in the first request.
  • The user approves and the browser carries a short-lived code back to the app.
  • The app trades the code and the verifier for an access token on a direct call.
  • The app calls the API with the access token as a bearer credential.

Knowing it is half the job. Saying it is the other half.

Interview Clozo is an AI interview copilot for real interview rounds: it hears the question and puts a strong answer on your screen, and you say it in your own words. See the features or how it works.

Start Free Trial →

Worked example

The numbers below come from a short script.1 The verifier is the sample string from Appendix B of RFC 7636, not a secret in use, and the challenge below matches the value printed there. RFC 7636 allows verifiers of 43 to 128 characters; this one is 43 characters long, which is what 32 random bytes produce when written in the URL-safe base64 alphabet: 32 bytes are 256 bits, and 256 divided by 6 bits per character, rounded up, is 43.

The app hashes the verifier with the Secure Hash Algorithm (SHA) function SHA-256, which has a 256-bit output, giving 32 bytes, then writes those bytes in the same alphabet. For the sample verifier the challenge is E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM, again 43 characters.1 The app sends that challenge in Step 1 and the verifier in Step 3, and the server repeats the hash to compare.

Token lifespan is the second number. Take an illustrative eight-hour working session of 480 minutes. An access token that lives 5 minutes means 96 token requests, one that lives 15 minutes means 32, and one that lives 60 minutes means 8.1 A leaked token works only until it expires, so shorter is safer, at the price of more traffic to the authorization server. Real lifespans are set by each provider, not by the framework. An illustrative refresh token that lives 30 days is 2,592,000 seconds, and an illustrative state value of 16 random bytes carries 128 bits.

A short-lived access token cuts a leaked token's useful life from an hour to five minutes, while a long-lived refresh token keeps the user signed in.
QuantityValue (computed or illustrative)
Random bytes behind the verifier32
Verifier length, URL-safe characters43
Challenge length (SHA-256, 32 bytes)43
Token requests in a 480-minute session, 5-minute tokens96
Token requests, 15-minute tokens32
Token requests, 60-minute tokens8
An illustrative 30-day refresh token, in seconds2,592,000
Random bytes in an illustrative state value16 (128 bits)
Shorter tokens mean more requests in an eight-hour sessionBar chart of illustrative token requests in a 480-minute session: 96 with 5-minute tokens, 32 with 15-minute tokens and 8 with 60-minute tokens.Token requests0501005 min15 min60 minAccess token lifespan96328Diagram: Interview Clozo, CC BY 4.0 ·interview.clozo.ai/blog/oauth.html
Shorter-lived tokens shrink the damage of a leaked token but multiply the refresh traffic.CC BY 4.0 — source: What is OAuth, and how does the code flow work?
Text description of the diagram
  • An illustrative 480-minute session needs 96 token requests with 5-minute tokens.
  • The same session needs 32 requests with 15-minute tokens and 8 with 60-minute tokens.

Trade-offs and edge cases

OAuth is not login. The framework decides what an app may do. A separate standard, OpenID Connect (OIDC), sits on top of OAuth and adds an ID token that tells the app who signed in. "Sign in with a provider" buttons normally use OIDC, which is why the two get confused.

OAuth grants access while OpenID Connect proves identityTable comparing OAuth and OpenID Connect by the question each answers, the main result, what it is built on and what it is used for.QuestionOAuthOpenIDConnectIt answerswhat may thisapp do?who is this user?Main resultaccess tokenID tokenBuilt onHTTPOAuthUse it forcalling an APIsigning a user inDiagram: Interview Clozo, CC BY 4.0 ·interview.clozo.ai/blog/oauth.html
OAuth decides what an app may do; OpenID Connect, built on it, tells the app who logged in.CC BY 4.0 — source: What is OAuth, and how does the code flow work?
Text description of the diagram
  • OAuth answers what an app may do and returns an access token.
  • OpenID Connect is built on OAuth and tells the app who the user is.

The code flow is one of four grant types that RFC 6749 defines: authorization code, implicit, resource owner password credentials and client credentials. The client credentials grant has no user at all; one backend service authenticates to another with its own identity. That fits server-to-server calls, such as the traffic behind a rate-limited API gateway.

The implicit grant returned the token straight in the browser. RFC 9700, §2.1.2 says it should not be used, because of access-token leakage and replay. The same document says public clients must use PKCE and confidential clients should (§2.1.1), and that the resource owner password credentials grant must not be used (§2.4). For browser and mobile apps, the answer is the code flow with PKCE.

Other edge cases: broad scopes make a leaked token costly, so ask for the least you need; a loose redirect match leaks codes and tokens; and a refresh token is a long-lived secret, so store it more carefully than the access token. RFC 9700, §2.2.2 says refresh tokens for public clients must be sender-constrained or use refresh token rotation, where each use returns a new refresh token and retires the old one. Sender-constraining ties a token to a key the client holds, for example with Demonstrating Proof of Possession (DPoP, RFC 9449) or mutual TLS (RFC 8705). Webhooks that a provider calls back on use a different trust mechanism, covered in what a webhook is.

How to answer it in an interview

Interviewer asks

What is OAuth and how does the authorization code flow work?

A strong answer

OAuth lets an app get limited access to a user's data on another service without the user's password. In the code flow, the app redirects the user to the authorization server with a scope, a random state value and a PKCE challenge. The user approves, and the server sends a short-lived code back. The app exchanges that code, plus the PKCE verifier, for an access token over a direct call, then sends the token as a bearer credential to the API. It is authorization, not login; for login I add OpenID Connect. The trade-off is that a bearer token works for anyone holding it, so I keep it short-lived.

The spoken structure: say what OAuth is for, walk redirect, approval, code, token and API call in order, then name the bearer-token risk and how you limit it.

Common mistakes

  • "OAuth is how users log in." (wrong) OAuth grants limited access to data. (right) "OAuth is authorization; OpenID Connect adds login on top."
  • "The browser gets the access token." (wrong) In the code flow the browser carries only a short-lived code. (right) "The token comes back on a direct call between the app and the authorization server."
  • "State is optional decoration." (wrong) Without state or PKCE protection, a forged response can be fed to the app. (right) "I check the returned state against the one stored in the session."
  • "Any redirect address on the same domain is fine." (wrong) A loose match can send the code to an attacker. (right) "Redirect addresses are registered and compared exactly."
  • "The access token is a JWT." (wrong) The framework does not fix a format. (right) "It may be an opaque string or a signed token, depending on the server."

Follow-up questions

What is the difference between OAuth 1.0 and OAuth 2.0?

OAuth 1.0 signed each request; OAuth 2.0 relies on bearer tokens sent over TLS. RFC 6749 obsoletes the earlier RFC 5849, and the two versions are not compatible.

Is OAuth authentication or authorization?

OAuth is authorization. It tells an API what a token holder may do, not who the person is. Authentication, the proof of who someone is, is done by the authorization server in its own way, and OpenID Connect standardizes the result.

What is the difference between OAuth and OpenID Connect?

OAuth returns an access token for calling APIs. OpenID Connect is built on OAuth and also returns an ID token that tells the app who signed in. Use OAuth alone when the app needs data access, and OpenID Connect when it needs the user's identity.

Why does the code flow return a code and not the token?

The code passes through the browser's address bar, where it can leak through history, logs or a forged redirect. RFC 9700 notes that exact redirect matching helps prevent leakage of codes and tokens. The token is issued only on a direct call, where a confidential client also authenticates, and PKCE makes a leaked code useless.

What is a refresh token and when is it used?

A refresh token is a long-lived credential that the app presents to the token endpoint to get a new access token when the old one expires. It lets access tokens stay short-lived without asking the user to approve again, and it needs careful storage.

Why use PKCE if the app already has a client secret?

A browser or phone app cannot keep a secret, because anyone can inspect it, so it has none to use. PKCE creates a fresh secret per request instead. Even a server-side app benefits, since the per-request secret defeats a stolen code. See also backend interview questions.

Key takeaways
  • OAuth is delegated authorization: an app gets a limited access token instead of the user's password.
  • The code flow sends the user to the authorization server, returns a short-lived code, and swaps it for a token on a direct call.
  • State blocks forged responses, PKCE makes a stolen code useless, and exact redirect matching keeps codes from leaking.
  • A bearer token works for whoever holds it, so keep it short-lived and send it only over encrypted connections.
  • OAuth is not login; OpenID Connect adds the identity layer.

Sources

  1. The OAuth 2.0 Authorization Framework (RFC 6749) — RFC Editor (IETF), 1 Oct 2012
  2. Best Current Practice for OAuth 2.0 Security (RFC 9700) — RFC Editor (IETF), 1 Jan 2025
  3. Proof Key for Code Exchange by OAuth Public Clients (RFC 7636) — RFC Editor (IETF), 1 Sep 2015
  4. OpenID Connect Core 1.0 — OpenID Foundation, 15 Dec 2023