skip to content

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

level: seniorimportance: should knowfreq 45%

answer

  1. the client sees the owner's password
  2. one credential, now in many places
  3. the authorization server never meets the user
  4. whole account, not a scoped grant
  5. RFC 9700 says MUST NOT

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.

solid answer

~50 s

The resource owner password credentials grant has the client collect the buyer's catalogue password and post it to the token endpoint as `grant_type=password` with `username` and `password`. Three things are wrong with that. The credential now exists in the client's form, memory, logs and support process, so the set of places it can leak is far larger than the authorization server alone. The authorization server never gets to run its own authentication ceremony with the buyer, so whatever it would have done beyond checking a password does not happen. And the client ends up holding a whole-account credential rather than a scoped, revocable grant. RFC 9700 states that this grant **MUST NOT** be used, and the OAuth 2.1 draft removes it. The replacements are the ones the taxonomy already has: the authorization code grant when a human is present, the client credentials grant when the partner's system acts for itself.

code

http · 8 lines
http
POST /token HTTP/1.1
Host: as.catalogue.example
Content-Type: application/x-www-form-urlencoded

grant_type=password
&username=buyer%40nursery.example
&password=the-buyers-catalogue-password
&scope=orders.write

go deeper

for a junior

Remember the rule and the reason: an application should never collect the password for someone else's service, because that password opens the whole account.

for a middle

Explain the mechanics — grant_type=password with username and password at the token endpoint — and why the exchange produces no scoped, revocable delegation.

for a senior

Show you can hold the line in a real negotiation: name the exposure paths, the skipped authentication ceremony, the correct strength of the prohibition, and the replacement grant for each caller.

for a principal

Own the migration: an estate still on this grant needs a sequenced move, a deadline, and a policy that no new integration collects a credential belonging to another system.

## What the partner is actually asking for The request is for the **resource owner password credentials grant**: the client gathers the owner's username and password in its own interface and exchanges them at the token endpoint for an access token. It was in RFC 6749 for one narrow purpose — migrating clients that *already* stored passwords, typically first-party ones — and that narrow purpose is now closed. ## Why it is refused - **The credential's blast radius widens.** A password held only by the authorization server exists in one place. Run it through a client and it exists in a form field, the client's process memory, whatever logging middleware sits in that request path, an error report, a screenshot in a support ticket, and the partner's staff who will inevitably read a few out over the phone. - **The authorization server is bypassed as an authenticator.** It receives a username and a password and nothing else. Anything it would have done with the user standing in front of it — a further factor, a step-up decision, a warning about an unfamiliar sign-in — simply does not run on this path, because there is no interaction to run it in. - **What the client receives is not delegation.** The buyer has not approved a scope for a named client; they have handed over the key to the account. Nothing about the exchange records *who* was granted *what*, and nothing withdraws it except changing the password. - **It trains the wrong reflex.** Users who are taught to type their catalogue password into a third party's screen will do it again, on a screen that is not the partner's. - **It cannot carry a delegation that is narrower than the account.** Even where the grant accepts a `scope` parameter, the client held the full credential on the way in, so the narrowing is a courtesy, not a boundary. ## How strong is the prohibition, and where does it come from? This is the part candidates get wrong, usually by flattening two different statements into "both old grants are deprecated": | Grant | Current best-practice wording | Status in the OAuth 2.1 draft | |---|---|---| | Resource owner password credentials | RFC 9700: **MUST NOT** be used | Removed | | Implicit | RFC 9700: clients **SHOULD NOT** use it | Removed | So the password grant carries the stronger prohibition of the two, and only the 2.1 draft deletes both outright. An authorization server may still implement the grant — many long-lived deployments do — and the fact that a token comes back is not evidence that the arrangement is acceptable. ## What to offer the partner instead 1. **A human is present.** Use the authorization code grant. The buyer authenticates at the authorization server and the partner's system receives a scoped token. This is the answer even when the partner insists their own users "expect" to log in inside their app. 2. **No human is involved.** Use the client credentials grant. The partner's system is a client with client credentials of its own; it does not need, and must not be given, a person's password. 3. **A device that cannot show a browser.** OAuth 2.0 defines a separate grant for input-constrained devices, which moves approval onto a second device rather than into a password field. The common counter-argument — "we are first-party, so it is our own users' password anyway" — is worth answering directly. Being first-party removes the trust question and none of the others: the credential still spreads across more systems, the authentication ceremony is still skipped, the grant is still unscoped, and the deployment still has no path to a second factor later without rewriting every client. ## The interview signal A weak answer says "it is deprecated". A strong one names the mechanism (the client sees the credential), the consequence (wider exposure, no server-side ceremony, whole-account reach), the correct strength of the rule (MUST NOT in RFC 9700, removed in the 2.1 draft, but still implemented in the wild), and the replacement grant for each of the partner's two callers.

  • The partner's system has no human at all — does that make this grant acceptable?
    No, it makes the case clearer. A machine caller should be a client with its own credentials under the client credentials grant. Inventing a human-shaped account with a password so a scheduled job can log in reproduces every problem of the password grant and adds an account nobody owns.
  • How strong is the prohibition, and who states it?
    RFC 9700 states that the resource owner password credentials grant MUST NOT be used, and the OAuth 2.1 draft removes it. That is stronger than its wording on the implicit grant, which clients SHOULD NOT use. A server implementing the grant is behind current practice rather than non-conformant with RFC 6749.
  • The partner says they are first-party, so the password is 'theirs' anyway. What do you answer?
    Being first-party removes the trust objection and none of the others. The credential still spreads into more systems and logs, the authorization server still never runs its own authentication with the user, the resulting access is still unscoped, and adding a further factor later would mean rewriting every client that collects the password.

saying these in an interview costs you the question

  • Defends it for first-party applications as current practice
  • Thinks TLS makes handling the owner's password acceptable
  • Gives it the same strength of prohibition as the implicit grant
  • Proposes storing the password to obtain tokens later
  • Assumes a machine caller must sign in as some user
  • Says the scope parameter makes the resulting access narrow