skip to content

Delegation Flows

How an application actually gets permission to act for someone: the code exchange and its proof key, the redirect that carries the code back, device flows and token exchange. Interviewers start here.

part ofOAuth 2.0overview, primer and where to startread it →
on this pageshow

questions

28

Why does an OAuth 2.0 client send the user to the authorization server to log in and then back?

level: juniorimportance: must knowfreq 75%

answer

  1. delegation, not a shared password
  2. the password never reaches the application
  3. browser out, direct call back
  4. a code is not a token
  5. response_type=code, then grant_type=authorization_code

basics

~20 s

The authorization code grant keeps the resource owner's password at the authorization server. The user authenticates there, and the client receives only a short-lived authorization code, which it exchanges on a back channel for a scoped access token.

solid answer

~40 s

That round trip is the **authorization code grant**, and it exists so the client never handles the resource owner's password. The client sends the browser to the authorization server's authorization endpoint with `response_type=code`, its `client_id`, a `redirect_uri` and the `scope` it wants. The resource owner authenticates and approves at the authorization server, which redirects the browser back to the client carrying a short-lived authorization code. The client then posts that code to the token endpoint as `grant_type=authorization_code` over a direct server-to-server call and gets back an `access_token` with `token_type` and `expires_in`. Two legs, two channels: the browser carries the request out and the code back; the token never travels through the browser at all.

code

http · 9 lines
http
GET /authorize?response_type=code
  &client_id=s6BhdRkqt3
  &redirect_uri=https%3A%2F%2Forders.nursery.example%2Fcb
  &scope=orders.write
  &state=af0ifjsldkj HTTP/1.1
Host: as.catalogue.example

HTTP/1.1 302 Found
Location: https://orders.nursery.example/cb?code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj

go deeper

for a junior

Recall the shape: the user logs in at the other site, the application gets a code, and the code is swapped for a token behind the scenes. The password never reaches the application.

for a middle

Explain the two legs and why they use different channels: the browser carries a code that is useless on its own, and the token arrives on a direct call the browser never sees.

for a senior

Show the consequences you have lived with: a client compromise does not expose account passwords, withdrawal of access is one record at the authorization server, and the token is bounded in scope and time.

for a principal

Frame the redirect as a boundary decision — which party is allowed to hold a credential to the whole account, and what it costs an estate when that boundary is crossed for convenience.

## What a grant is, and why the redirect is one OAuth 2.0 calls the resource owner's permission an **authorization grant**. `grant_type` is the value the client sends to the **token endpoint** naming which flow produced that permission. The redirect-based one is `authorization_code`, and it is the grant behind almost every "connect your account" button. The design it replaces is the obvious one: ask the buyer for their wholesale catalogue password and log in as them. That is precisely what the framework exists to avoid. A password is a credential to the *whole* account, for an unbounded time, at every interface the account has. A delegated grant is a credential to *one slice* of the account, for a bounded time, issued to *one named client*. ## The two legs 1. **Front channel (through the browser).** The garden centre's ordering integration sends the buyer's browser to the authorization server's authorization endpoint with `response_type=code`, its `client_id`, its registered `redirect_uri`, the `scope` it is asking for, and a `state` value it will check when the browser comes back. The buyer authenticates *at the authorization server* and approves. 2. **Back channel (server to server).** The authorization server redirects the browser to the client's redirection endpoint with a short-lived authorization code in the query string. The client then makes a direct HTTP request to the token endpoint with `grant_type=authorization_code` and that code, and receives a token response containing `access_token`, `token_type` and `expires_in`. | Leg | Carried by | Carries | Who can read it | |---|---|---|---| | Authorization request | The browser, as a redirect | `response_type=code`, `client_id`, `redirect_uri`, `scope` | The user, and anything with sight of the browser | | Authorization response | The browser, as a redirect back | A short-lived authorization code | The user, and anything with sight of the browser | | Token request and response | A direct call from the client | `grant_type=authorization_code`, then the access token | Only the client and the authorization server | The split is the whole point. The visible, tamperable leg carries something that is **not usable on its own**; the usable thing is fetched over a leg the browser never sees. ## What the redirect actually buys - **The password stays where it was set.** The client's code, logs, memory and support desk never contain it, so a compromise of the client is not a compromise of the account's password. - **The authorization server keeps control of the authentication ceremony.** Whatever it does beyond checking a password — a second factor, a step-up, a risk decision — still happens, because the user is standing in front of it. - **The resource owner sees who is asking.** Approval happens on the authorization server's own pages, for a named `client_id` and a named `scope`. - **What the client gets is bounded.** An `access_token` carries a scope and an `expires_in`; a password carries neither. - **Withdrawal is one record.** Ending the client's access is a decision at the authorization server, not a password change that breaks everything else the buyer uses. ## What the client never learns It never learns the resource owner's password, and it never learns anything the authorization server did not put in the token response or in the token itself. An access token obtained this way says *what the client may do*; it is not, on its own, a statement about who is at the keyboard — a separate identity layer exists for that question. ## When the redirect is the wrong shape The redirect assumes two things: a resource owner is **present**, and the client can **get a browser in front of them**. Remove either assumption and this grant stops applying: - A nightly stock-and-price synchronisation runs at 03:00 with nobody to redirect. There is no resource owner delegating anything; the client acts for itself, which is the `client_credentials` grant. - A device with no usable browser or keyboard cannot render an authorization page at all. OAuth 2.0 defines a separate grant for input-constrained devices, which moves the approval onto a second device the user already holds. So the answer to "why the redirect?" is not "because that is how the library works". It is: the only party entitled to see the resource owner's password is the authorization server, so the flow is arranged to put the user in front of it — and the code that comes back is deliberately worthless until the client redeems it somewhere the browser cannot reach.

  • Which part of this exchange travels through the browser, and which does not?
    The authorization request and the authorization response both travel through the browser as redirects, so the user and anything watching the browser can see them. The code exchange does not: the client posts `grant_type=authorization_code` to the token endpoint on its own connection, and the access token comes back on that same direct connection.
  • What does the client send to the token endpoint, and what comes back?
    A form-encoded POST carrying `grant_type=authorization_code`, the code, and the same `redirect_uri` that was used on the authorization request. The response is JSON with `access_token`, `token_type` and `expires_in`, and it may include a refresh token so the client can carry on once the resource owner has gone.
  • Does completing this grant tell the client anything about which human approved it?
    Not by itself. The grant produces an access token that says what the client may do at a resource server. Establishing who authenticated is a separate identity layer built on top of these grants, with its own token and its own rules.

A contractor signs a visitor in at the building's own reception; reception hands the contractor a numbered slip, which the security desk swaps for a pass that opens one floor until six o'clock. The contractor never learns the visitor's door code.

saying these in an interview costs you the question

  • Says the client collects the user's password and forwards it
  • Calls the authorization code an access token
  • Thinks the code is exchanged through the browser
  • Says the code can be redeemed repeatedly for more tokens
  • Assumes every OAuth 2.0 grant involves a redirect
open as a page

Why does RFC 8252 have a native mobile app open its OAuth 2.0 authorization request in the device's browser rather than an embedded web view?

level: juniorimportance: must knowfreq 55%

basics

~20 s

RFC 8252 keeps the authorization request in an external user-agent because an embedded web view runs inside the application: the application can observe what is typed into it, including the resource owner's credentials, and it shares no signed-in session with the browser.

open as a page

In an OAuth 2.0 authorization-code flow, what attack does PKCE (RFC 7636) exist to stop?

level: juniorimportance: must knowfreq 66%

basics

~20 s

PKCE stops authorization-code interception. An attacker who captures the code as it travels back through the browser cannot redeem it, because the token request must also carry a code_verifier that only the application which started the flow holds.

open as a page

What must a device-grant client do when the token endpoint answers slow_down, and what interval applies if none was sent?

level: middleimportance: must knowfreq 50%

basics

~20 s

A slow_down answer means the client must add 5 seconds to its polling interval for this and every later request — a permanent increase, not a one-off pause. Where the response supplied no interval, the client must use 5 seconds.

open as a page

How does a device with no browser redeem its device_code at the token endpoint, and with which grant_type?

level: middleimportance: must knowfreq 56%

basics

~10 s

The device POSTs to the token endpoint with grant_type set to urn:ietf:params:oauth:grant-type:device_code, plus its device_code and client_id. Until the user approves it gets an error response carrying authorization_pending, then a normal token response.

open as a page

Which OAuth 2.0 grant fits a browser buyer placing an order, and which fits an unattended nightly stock sync?

level: middleimportance: must knowfreq 68%

basics

~20 s

The buyer's order uses the authorization code grant, because a resource owner is present and can be redirected. The nightly sync uses the client credentials grant, because no resource owner exists and the client is acting for itself.

open as a page

After a native app's OAuth 2.0 authorization request opens in the device's browser, how does the response reach the app?

level: middleimportance: must knowfreq 58%

basics

~20 s

RFC 8252 defines three redirect forms for a native client: a private-use URI scheme the operating system dispatches to the application, a claimed https URI the platform routes to it, and a loopback address the application is itself listening on.

open as a page

In PKCE, which OAuth 2.0 request carries the `code_challenge` and which carries the `code_verifier`?

level: middleimportance: must knowfreq 60%

basics

~20 s

The code_challenge and code_challenge_method travel on the front-channel authorization request; the raw code_verifier travels on the back-channel token request, where the authorization server re-derives the challenge and compares it with the one stored against that code.

open as a page

In an RFC 8693 token exchange, what do `subject_token` and `actor_token` each identify?

level: middleimportance: must knowfreq 50%

basics

~20 s

subject_token carries the party the new token is to be about, and that identity lands in the issued token's sub claim. The optional actor_token carries the party that will act for that subject. Sending both asks for delegation.

open as a page

In a token minted by an RFC 8693 exchange, what does an `act` claim tell a resource server that its absence does not?

level: seniorimportance: must knowfreq 48%

basics

~20 s

An act claim names the party currently acting for the token's subject, so a resource server sees both identities: delegation. Without it the token speaks only as the subject and the acting party leaves no trace: impersonation.

open as a page

In the OAuth 2.0 device authorization grant, what does a browserless device display, and where does the user approve it?

level: juniorimportance: should knowfreq 44%

basics

~20 s

The device displays a short user_code and a verification_uri. The user opens that URI on a separate phone or laptop, signs in there and enters the code. The device keeps a long device_code the user never sees.

open as a page

In OAuth 2.0, what does an RFC 8693 token-exchange request send to the token endpoint, and what comes back?

level: juniorimportance: should knowfreq 30%

basics

~20 s

An RFC 8693 token exchange is a back-channel POST to the token endpoint with grant_type set to urn:ietf:params:oauth:grant-type:token-exchange, a subject_token and its subject_token_type. The response returns a new token in access_token plus a required issued_token_type.

open as a page

Why was the implicit grant, which returned an access token straight from the authorization response, abandoned?

level: middleimportance: should knowfreq 40%

basics

~20 s

It delivered the access token through the browser in the redirect's URL fragment, with no back-channel exchange and no standardised way to bind the token to anything. The constraint that justified it, a browser script unable to call the token endpoint, no longer exists.

open as a page

Why does RFC 6749 say a client credentials token response should not include a refresh token?

level: middleimportance: should knowfreq 50%

basics

~20 s

The refresh token grant exists to renew an access token while the resource owner is absent. The client credentials grant has no resource owner to be absent: the client can authenticate again at any moment, so a refresh token adds exposure and no capability.

open as a page

Why must an authorization server accept any port on a native client's loopback redirect URI at request time?

level: middleimportance: should knowfreq 42%

basics

~20 s

Because the native client does not choose the port: it asks the operating system for an available one when it opens its temporary listener, so the number is unknown until the flow starts. RFC 8252 section 7.3 therefore allows any port at request time.

open as a page

Why does PKCE's `S256` method protect an observed authorization request when `plain` does not?

level: middleimportance: should knowfreq 54%

basics

~10 s

With plain the code_challenge is the code_verifier itself, so whatever reads the authorization request holds both halves. S256 puts only BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) on that request, and a digest cannot be turned back into the verifier.

open as a page

How does an RFC 9126 pushed authorization request change what the browser carries to the authorization endpoint?

level: middleimportance: should knowfreq 42%

basics

~20 s

Pushed authorization requests move the parameters off the browser. The client POSTs them to the authorization server's pushed authorization request endpoint, receives a short-lived request_uri reference, and the browser redirect then carries only client_id and that reference.

open as a page

In RFC 9396, what can an authorization_details entry express about a requested right that a scope string cannot?

level: middleimportance: should knowfreq 34%

basics

~20 s

Structure. An authorization_details entry is a JSON object with a required type plus members such as locations, actions, datatypes, identifier and privileges, so one request can name the resource, the operation and the limits — where a scope string is a single opaque label.

open as a page

Why is a device-grant user_code kept short, and what must the authorization server do about the guessing risk?

level: seniorimportance: should knowfreq 38%

basics

~20 s

The user_code is retyped by a human on a second device, so it is short, case-insensitive and drawn from a reduced character set. That costs entropy, and the compensation sits with the authorization server: rate-limit attempts at the verification page and keep the code short-lived and one-time.

open as a page

Why is the resource owner password credentials grant refused when a partner asks your client to collect buyers' passwords?

level: seniorimportance: should knowfreq 45%

basics

~20 s

That grant puts the resource owner's password inside the client, which multiplies where the credential can leak, removes the authorization server's own authentication ceremony, and gives the client whole-account reach instead of a scoped grant. RFC 9700 says it MUST NOT be used.

open as a page

A second installed application declares the same private-use URI scheme as your native OAuth 2.0 client — where does the authorization response go?

level: seniorimportance: should knowfreq 34%

basics

~20 s

Wherever the operating system decides. A private-use URI scheme has no naming authority, so nothing stops a second application declaring the same string, and the platform's own resolution rule — not the specification — picks which one is handed the authorization response.

open as a page

Your authorization server ignores the `code_verifier` when the authorization request carried no `code_challenge` — what does that allow?

level: seniorimportance: should knowfreq 44%

basics

~20 s

It allows a PKCE downgrade. An attacker who can alter the front-channel authorization request strips the code_challenge, the server binds nothing to the code it issues, and an intercepted code is then redeemed with no verifier at all — reopening the hole PKCE closed.

open as a page

What does signing an authorization request as an RFC 9101 request object prove that pushing it does not?

level: seniorimportance: should knowfreq 36%

basics

~20 s

A signed request object carries its own proof of authorship. The signature travels with the parameters, so an authorization server can verify who composed them even after the request has passed through a browser or been relayed by another party.

open as a page

In an RFC 8693 token exchange, how do the `audience` and `resource` parameters narrow the issued token, and when does the server answer `invalid_target`?

level: seniorimportance: should knowfreq 38%

basics

~20 s

audience and resource name the service the issued token should be good for, and the authorization server reflects that into the token's aud claim. When it cannot or will not issue for the named target, it answers invalid_target.

open as a page

What would make you move an estate's delegated rights from scope strings onto RFC 9396 authorization_details?

level: principalimportance: should knowfreq 28%

basics

~20 s

Move when the rights you delegate carry parameters — a specific resource, a limit, a date range — and teams are encoding those parameters inside scope strings by private convention. That convention is an unwritten contract with no protocol support and no error when parties disagree.

open as a page

Why must a PKCE `code_verifier` be fresh random data rather than a value the client can derive?

level: middleimportance: nice to knowfreq 33%

basics

~20 s

Because the only thing PKCE guarantees is that the redeemer can produce a value nobody else can. A verifier derived from data an attacker can obtain, or reused across flows, can be recomputed or replayed, and an intercepted code becomes redeemable again.

open as a page

What can an authorization server not tell about a client from a claimed https redirect URI it registered?

level: seniorimportance: nice to knowfreq 26%

basics

~20 s

It cannot tell that the client is a native application. A claimed https redirect URI is an ordinary HTTPS URL on the wire, identical to what a web client registers, and the diversion to an installed application happens on the device where the server cannot see it.

open as a page

Why does a client that caches and replays one pushed-authorization request_uri get its authorization requests rejected?

level: seniorimportance: nice to knowfreq 25%

basics

~20 s

Because the reference is short-lived and meant for one attempt. RFC 9126 expects a brief expires_in, requires the client to use a value once, and the authorization server is expected to treat it as one-time use, tolerating at most a browser refresh.

open as a page