Resource Owner Password Credentials
The Resource Owner Password Credentials (ROPC) grant allows a client to exchange a username and password directly for tokens, without going through the browser authorization flow.
Request
Section titled “Request”curl -X POST https://auth.example.com/oauth2/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=password" \ -d "username=alice" \ -d "password=secret" \ -d "client_id=my-client-id" \ -d "scope=openid profile email" \ -d "totp_code=123456"Parameters
Section titled “Parameters”| Parameter | Required | Description |
|---|---|---|
grant_type |
Yes | Must be password |
username |
Yes | The user’s username |
password |
Yes | The user’s password |
client_id |
Yes | The client identifier |
scope |
No | Space-separated list of scopes (defaults to client’s allowed scopes, or openid profile email) |
totp_code |
Conditional | Required when MFA is enforced (see MFA enforcement below) |
Response:
{ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "id_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 900, "scope": "openid profile email"}Enabling for a client
Section titled “Enabling for a client”The client must have password in its grant_types. When registering:
curl -X POST https://auth.example.com/oauth2/register \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "client_name": "My CLI Tool", "redirect_uris": ["http://localhost"], "grant_types": ["password", "refresh_token"], "client_type": "public" }'MFA enforcement
Section titled “MFA enforcement”MFA is fully enforced in the ROPC flow. When the global require_mfa setting is enabled or the user has TOTP enrolled, the totp_code parameter is required. The server responds with specific error codes:
mfa_required(HTTP 403) — returned when TOTP is enrolled buttotp_codewas not provided, or whenrequire_mfais enabled but the user has not yet enrolled in TOTP (the user must enroll via the browser login flow first)invalid_mfa_code(HTTP 403) — returned when the providedtotp_codeis incorrectmfa_locked(HTTP 403) — returned after five failed TOTP attempts on an account, and while its MFA cooldown is active
TOTP failures have a separate account-level counter. Correct passwords and changes of source IP do not reset it. The cooldown uses account_lockout_duration, falling back to 15 minutes when that setting is zero or negative. After the cooldown, verification starts a new budget; successful TOTP verification or an administrator unlocking the account clears the counter. Disabling password lockout does not disable this TOTP limit.
Only TOTP codes are supported in the ROPC flow. Email OTP is not available because there is no interactive session to complete the challenge. See Multi-Factor Authentication for details on MFA setup and enrollment.
Limitations
Section titled “Limitations”- Passkey authentication is not available — ROPC only supports username/password
- Email OTP is not available — only TOTP codes can be used for MFA in ROPC
- No SSO session is created — each ROPC token exchange is independent
- Account lockout still applies — repeated failed password attempts will lock the account
When require_email_verification is enabled, unverified non-admin users cannot obtain tokens through the password grant. The endpoint returns HTTP 400 invalid_grant with Email verification is required; users must finish email verification first. The browser flow’s admin recovery exemption also applies here.