Password Grant
The password grant (grant_type=password, Resource Owner Password Credentials in RFC 6749 §4.3) lets your application send a user’s email — or username — and password straight to /oauth/token and get tokens back, with no browser redirect.
Use it only when your own app cannot open the hosted login — a legacy client, an embedded device, a migration. Your app sees the password, and the user gets none of what the hosted screen gives: passkeys, social sign-in, single sign-on across your apps, the login flows you configure. For a user signing in, Authorization Code with PKCE is the default.
Turn it on for a client
It is off for every client until you add password to the client’s grant_types:
POST /client/<client_id>
Content-Type: application/json
{ "grant_types": ["authorization_code", "refresh_token", "password"] }A client that has not opted in gets 400 unauthorized_client.
Request tokens
curl -X POST https://<your-auth-domain>/oauth/token \
-H 'content-type: application/x-www-form-urlencoded' \
-d grant_type=password \
-d client_id=<client_id> \
-d client_secret=<client_secret> \
-d username=ana@example.com \
-d password='the-password' \
-d scope='openid profile email offline_access'| Parameter | Required | Notes |
|---|---|---|
grant_type | yes | password |
client_id | yes | |
client_secret | for confidential clients | Not needed for a public client (registered with token_endpoint_auth_method: none) |
username | yes | An email or a username, as the database connection’s sign-in identifier allows |
password | yes | |
realm | no | The name of the database connection. Defaults to the first database connection offered to the client |
scope | no | As in any other grant |
audience | no | The API the access token is for |
The response is the same as any other user grant:
{
"token_type": "Bearer",
"access_token": "eyJ…",
"expires_in": 3600,
"id_token": "eyJ…",
"refresh_token": "…"
}Two-step verification
If the tenant’s policy asks this user for a second factor, the grant stops with 403 and error: mfa_required, carrying an mfa_token and the factors the user can use (mfa_required_factors). Send the code with grant_type=http://auth0.com/oauth/grant-type/mfa-otp and that token to finish — the same second step as the emailed-code grant. See Two-Step Verification.
Failed attempts
After 10 failed attempts in 15 minutes for the same email or username from the same network, every attempt — even with the right password — gets 429 with error_code: too_many_login_attempts until the window passes. A successful sign-in resets the count. The hosted login form shares the same count, so switching between the two does not reset it.
Counting per network as well as per user means someone who knows an email cannot lock that person out from everywhere.
Errors
Errors follow RFC 6749 §5.2 — error and error_description — plus error_code when error is too coarse:
| Status | error | error_code | Why |
|---|---|---|---|
| 400 | unauthorized_client | unauthorized_client | The client did not opt in to the password grant |
| 401 | invalid_client | invalid_client | Missing or wrong client_secret for a confidential client |
| 400 | invalid_request | invalid_connection | realm does not name a database connection offered to the client |
| 400 | invalid_grant | invalid_credentials | Wrong email/username or password |
| 403 | invalid_grant | user_suspended | The user is suspended |
| 403 | mfa_required | — | A second factor is needed — see above |
| 429 | invalid_grant | too_many_login_attempts | Too many failed attempts from this network — see above |
Last updated on