Resource Owner Password Credentials (ROPC)
This page helps you keep an old app that signs users in with the password grant working, and move it off.
In the password grant, your app asks the user for their email and password, and sends them to the token endpoint, which answers with tokens. The user never sees the auth server’s sign-in page, so your app sees their password, and nothing but a password can be checked.
When to turn it on
Section titled “When to turn it on”Turn it on only for an app of your own that signs users in this way and that you can’t change yet, and only for that app’s client, while you move it to the authorization code flow. Leave the global setting off, so no other client gets it by accident. Never turn it on for an app someone else wrote: a user should type their password into the auth server and nowhere else.
Turn it on for one client
Section titled “Turn it on for one client”-
In the admin console, open Admin, Clients and click Manage beside your app’s client.
-
On OAuth2 flows, under Legacy flows (deprecated in OAuth 2.1), set Resource Owner Password Credentials (ROPC) to Enabled, and click Save.
-
Send the user’s email and password to the token endpoint, with your client’s credentials. A public client leaves
client_secretout:Terminal window curl -X POST https://auth.example.com/auth/token \-d grant_type=password \-d client_id=legacy-app \-d client_secret=my-secret \--data-urlencode password=the-users-password \-d "scope=openid email" -
Read the tokens from the answer:
HTTP/1.1 200 OKContent-Type: application/jsonCache-Control: no-storePragma: no-cache{"access_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ii4uLiJ9...","id_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ii4uLiJ9...","token_type": "Bearer","expires_in": 300,"refresh_token": "eyJhbGciOiJSUzI1NiIsImtpZCI6Ii4uLiJ9...","refresh_expires_in": 2592000,"scope": "openid email"} -
Forget the password as soon as the answer comes back. Use the refresh token when the access token expires, as for any other grant. See Token.
Resource Owner Password Credentials (ROPC) on the OAuth2 flows tab has three choices: Enabled, Disabled, or inherit the global Resource owner password credentials flow enabled under Admin, General, which is off in a new install.
The request
Section titled “The request”| Parameter | Required | |
|---|---|---|
grant_type |
Yes | password |
username |
Yes | The user’s email address. Spaces around it are trimmed, and case doesn’t matter. |
password |
Yes | The user’s password |
scope |
No | The scopes to ask for, separated by single spaces. openid when left out. |
client_id |
Yes | The client’s identifier |
client_secret |
For a confidential client | Its secret, in the form body or as Authorization: Basic |
The scope can hold the OpenID Connect scopes, such as openid, profile and email, offline_access, and resource:permission scopes the user holds, directly or through a group. A scope the user doesn’t hold is refused, never dropped. An administrative scope needs a client allowed to request one.
What your app gets
Section titled “What your app gets”- An access token and a refresh token, always, and an ID token when the scope has
openid. - An offline refresh token, whether or not your app asked for
offline_access, since there’s no session for it to belong to. It follows the offline refresh token’s idle timeout and maximum lifetime, 30 days and a year in a new install. See Refresh tokens. - No consent screen. Sending the password counts as the user’s consent to the scope asked for.
acrisurn:goiabada:level1andamris["pwd"], whatever the client’s default ACR level, since a password is all that was checked. An API that requires two-factor authentication refuses these tokens by theiracr. See ACR and AMR.- No
sid. The tokens belong to no session, so signing out of the browser doesn’t touch them. auth_timeis when the password was checked, and stays that across every refresh.
Each grant leaves a token_issued_ropc_response entry in the audit log. Each invalid_grant below leaves a ropc_auth_failed entry, which records the address only as email_digest.
Who can’t use it
Section titled “Who can’t use it”- A user with two-factor authentication. The grant can’t ask for a one-time code, so it refuses every user who has an authenticator rather than skip the second factor. They sign in through the browser instead.
- A disabled user, even with the right password.
Turning it off
Section titled “Turning it off”Setting the flow to Disabled, for the client or globally, stops new grants and refresh tokens already issued alike: the next refresh is refused with unauthorized_client, and the user has to sign in another way.
Rate limits
Section titled “Rate limits”RFC 6749 section 4.3.2 requires the endpoint to be protected against guessing. A wrong password counts against the same budgets as one typed into the sign-in page, and the one for each account, 100 wrong passwords an hour, always applies. With the rate limiter on, the password grant also has a budget per IP address for every request, and a tighter one for wrong passwords for one username from one network. See rate limits and Too many attempts or 429.
Errors
Section titled “Errors”Errors are JSON, as for every grant, with error and error_description:
error |
Status | When |
|---|---|---|
unauthorized_client |
400 | The flow is off for the client |
invalid_request |
400 | username, password or client_id is missing, a public client sent a client_secret, or the secret came both in the Authorization header and in the body |
invalid_client |
401 | The client secret is missing or wrong, or the client doesn’t exist or is disabled. The answer carries WWW-Authenticate: Basic realm="goiabada". |
invalid_grant |
400 | The email or password is wrong, the user is disabled, or the user has two-factor authentication |
invalid_scope |
400 | A scope doesn’t exist or the user doesn’t hold it, or an administrative scope the client may not request |
A user with two-factor authentication who sends the right password is told why:
{ "error": "invalid_grant", "error_description": "Resource owner password credentials grant is not available for accounts with two-factor authentication enabled. Please use the authorization code flow instead."}