Which OAuth 2.0 grant fits a browser buyer placing an order, and which fits an unattended nightly stock sync?
answer
- ask who is present, then on whose behalf
- nobody to redirect means no redirect grant
- client_credentials has no resource owner
- one token cannot carry a buyer and no buyer
- unsupported_grant_type is the server, not the client
basics
~20 sThe 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.
solid answer
~40 sGrant selection follows two facts about the caller, not the convenience of a library. First: **is a resource owner present and redirectable?** The buyer is, so the ordering integration uses `grant_type=authorization_code` and the buyer approves at the authorization server. The nightly stock-and-price sync has nobody to redirect, so it uses `grant_type=client_credentials`: the client authenticates as itself and receives a token for its own access, with a scope decided when the client was set up rather than by anyone approving at run time. Second: **who can keep a secret?** — that decides how the client proves who it is, not which grant it qualifies for. The two callers cannot share one grant, because the buyer's token must be limited to the buyer's data while the sync's token has no user behind it at all.
code
http · 17 linesPOST /token HTTP/1.1
Host: as.catalogue.example
Authorization: Basic <base64 of client_id:client_secret>
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials&scope=stock.read%20prices.read
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
{
"access_token": "2YotnFZFEjr1zCsicMWpAA",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "stock.read prices.read"
}go deeper
Remember the two cases: a person at a browser gets the redirect-based grant, and a scheduled job with nobody present gets the grant where the client asks for a token for itself.
Explain the decision rule and the mechanics of each flow — one redirect plus a code exchange, versus a single back-channel request — and say why a machine caller needs no redirect.
Show the failure you have debugged: a token with no user behind it accepted as if it had one, or a batch job wired to a flow that waits for an approval that never comes.
Treat grant selection as a policy an estate enforces, not a per-integration choice, so that every unattended caller is a registered client rather than a human account with a stored password.
## The selection rule The taxonomy looks like a menu and is really a decision. Two questions settle almost every case: 1. **Is there a resource owner, and can you put a browser in front of them?** 2. **Is the client acting for that owner, or for itself?** Everything else — which library is easiest, what the sample code does, what the partner did last time — is noise. A grant is a claim about who authorised what, so choosing the wrong one makes the authorization server issue a token whose meaning does not match the request behind it. ## The garden centre's two callers | | Buyer placing an order | Nightly stock and price sync | |---|---|---| | Resource owner present | Yes, at a keyboard | No, it runs at 03:00 | | Acting for | That buyer's account at the catalogue | The integration itself | | Grant | `authorization_code` | `client_credentials` | | Approval | The buyer approves at the authorization server | Decided when the client was set up | | Token means | "This client may act on this buyer's behalf, within this scope" | "This client may do this, within this scope" | | Refresh token | May be issued, so the client can continue once the buyer leaves | RFC 6749 says one SHOULD NOT be included | The last two rows are why one grant cannot serve both. A token from the buyer's flow is bounded by *whose* data it reaches; a token from the sync is bounded only by *what* the integration may do. Collapsing them gives a batch job a human's reach, or gives a buyer's session the batch job's. ## The client credentials grant in detail There is no resource owner anywhere in this grant. The client authenticates at the token endpoint and asks for a token for itself, so the flow is a single back-channel exchange with no redirect, no authorization endpoint and no `redirect_uri`. Because the client can authenticate again whenever it likes, a refresh token adds a second long-lived credential with no capability the client did not already have — which is why RFC 6749 says the response SHOULD NOT include one. Two consequences interviewers push on: - **A resource server must not map such a token onto a user.** No human delegated anything. If the token carries a `sub`, it identifies the client, not a person; treating it as a user hands a scheduled job whatever that user may do. - **A "service account" with a password is not this grant.** Creating a human-shaped account for a machine and logging it in is the arrangement the retired password grant encoded. The client credentials grant exists so a machine caller is a *client*, with client credentials, not a pretend person. ## What the errors tell you when the choice is wrong The token endpoint distinguishes two failures that candidates routinely merge: - `unsupported_grant_type` — the authorization server does not implement that grant at all. Nothing about your client will fix it; either the server gains the grant or you pick another. - `unauthorized_client` — the server implements the grant, and this authenticated client is not allowed to use it. That is a registration or policy change on the client record. Both arrive as a `400` with a JSON error body; `error_description` is the free-text field that usually tells you which of the two situations you are in when a server has been sloppy about the code. A third, `invalid_grant`, is about the grant *material* presented — a code that is expired, already used, or issued to someone else — not about the grant *type*. ## The judgement being tested An interviewer asking this is checking whether the candidate reasons from the caller or from the tutorial. Strong answers name the two facts (presence of an owner, and on whose behalf the call is made), assign a grant to each caller, and say what would go wrong under the other choice: an unattended job that cannot run because it waits for a redirect nobody will complete, or a buyer's order placed under a token that carries no buyer at all and therefore cannot be scoped to their account. A weak answer reaches for whichever grant the client library documents first, or proposes one token for both because "the scopes are different anyway".
- A token request returns `400` with `unsupported_grant_type`. How does that differ from `unauthorized_client`?`unsupported_grant_type` means the authorization server does not implement that grant at all, so no change to your client helps. `unauthorized_client` means the server implements it but this authenticated client is not permitted to use it, which is a change to the client's registered grant types. A third code, `invalid_grant`, is about the material presented rather than the type.
- Why should a resource server not map a `client_credentials` access token onto a user account?Because no resource owner took part in issuing it. Any subject identifier in such a token names the client, not a person, so resolving it to a user account silently grants a scheduled job everything that user may do — and makes the audit trail claim a human acted when none did.
- The partner proposes one grant for both callers to keep the integration simple. What breaks?Either the nightly job stalls waiting for a redirect nobody completes, or the buyer's order is placed under a token that carries no buyer and therefore cannot be limited to their account. The two tokens mean different things, and the resource server's checks depend on which meaning it is given.
saying these in an interview costs you the question
- Picks the grant the library documents first, not the one the caller fits
- Uses client credentials for a token that must act for one buyer
- Thinks the client credentials grant needs a redirect_uri
- Proposes a service user with a password for the nightly job
- Says one grant serves both callers if the scopes differ
- Merges unsupported_grant_type with unauthorized_client