OAuth2 Resource Owner Password Grant — Direct Credential Authentication
In this tutorial, you will learn about OAuth2 Resource Owner Password Grant. We cover key concepts, practical examples, and best practices to help you master this topic.
The OAuth2 Resource Owner Password Credentials (ROPC) grant allows a client to exchange a user's username and password directly for an access token.
What You'll Learn
How ROPC works, when it is appropriate (very few cases), security risks, and why it is being deprecated in favor of the Authorization Code grant with PKCE.
Why It Matters
ROPC is the most controversial OAuth2 grant. It requires the client to handle user passwords directly — the exact problem OAuth2 was designed to avoid. Understanding ROPC helps you recognize when you should NOT use it and why alternatives are better.
Real-World Use
ROPC is sometimes used for first-party applications (the company that owns the API also owns the app) where the user trusts the application implicitly. However, even this use case is being deprecated.
flowchart LR
A["User"] -->|"Username + Password"| B["Client App"]
B -->|"POST /token\ngrant_type=password"| C["Auth Server"]
C -->|"Access Token + Refresh Token"| B
B -->|"API call + Bearer token"| D["Resource Server"]
D -->|"Data"| B
B -->|"Shows data"| A
style A fill:#dbeafe,stroke:#2563eb
style B fill:#fecaca,stroke:#dc2626
style C fill:#fef3c7,stroke:#d97706
style D fill:#dcfce7,stroke:#16a34a
Code Example: ROPC Implementation
import requests
TOKEN_URL = "https://auth.example.com/oauth/token"
API_URL = "https://api.example.com/user/profile"
CLIENT_ID = "trusted-app"
# Step 1: Exchange username/password for token
response = requests.post(TOKEN_URL, data={
"grant_type": "password",
"username": "user@example.com",
"password": "user-password",
"client_id": CLIENT_ID,
"scope": "profile"
})
token_data = response.json()
access_token = token_data["access_token"]
refresh_token = token_data.get("refresh_token")
print(f"Access token: {access_token[:20]}...")
# Step 2: Use token
headers = {"Authorization": f"Bearer {access_token}"}
profile = requests.get(API_URL, headers=headers)
print(profile.json())
Why ROPC Is Dangerous
| Risk | Description |
|---|---|
| Password Exposure | The client application handles plain-text passwords |
| No Granular Consent | The user cannot grant specific scopes — it is all or nothing |
| Credential Reuse | Users often reuse passwords across services |
| No MFA Support | Password grant cannot handle multi-factor authentication |
| Deprecated | OAuth2 Security BCP recommends against it; many providers reject it |
Code Example: Why Password Grant Fails with MFA
# Attempting password grant when MFA is enabled
response = requests.post(TOKEN_URL, data={
"grant_type": "password",
"username": "user@example.com",
"password": "user-password",
"client_id": CLIENT_ID
})
# Response when MFA is required
print(response.status_code) # 400
print(response.json())
# {"error": "invalid_grant", "error_description": "MFA required"}
The password grant cannot handle MFA challenges. The Authorization Code grant with redirect-based authentication supports MFA naturally.
Common Mistakes
1. Using Password Grant for Third-Party Apps
Third-party apps should never see the user's password. Use Authorization Code grant to keep passwords between the user and the authorization server.
2. Not Handling MFA
Password grant fails when MFA is enabled. The error does not indicate whether the password was correct, creating a poor user experience.
3. Storing Passwords in the Client
The client should discard the password immediately after exchanging it for a token. Some apps store passwords for "convenience" — this is a security disaster.
4. Confusing Password Grant with Client Credentials
Password grant uses user credentials. Client Credentials uses application credentials. They serve different purposes.
5. Believing Password Grant Is Secure
Even with HTTPS, password grant exposes the password to the client application. A malicious or compromised client can capture the password.
Practice Questions
- What grant type uses username and password directly?
- Why is ROPC considered less secure than Authorization Code?
- What happens when a user has MFA enabled and uses password grant?
- Is ROPC appropriate for third-party applications?
- What is the recommended alternative to ROPC?
Answers:
- Resource Owner Password Credentials (ROPC) grant, with
grant_type=password. - The client handles plain-text passwords. Authorization Code keeps passwords between the user and the authorization server.
- The password grant fails because it cannot handle MFA challenges. The authorization server may return
invalid_granterror. - No. Third-party apps should never see user passwords. ROPC is only for highly trusted first-party applications.
- Authorization Code grant with PKCE provides the same user experience without exposing passwords to the client.
Challenge: Convert a password-grant authentication flow to Authorization Code with PKCE. Explain how this improves security and what the user experience differences are.
FAQ
Mini Project
Write a Python script that demonstrates why password grant fails with MFA, then implement the same scenario using Authorization Code grant where MFA works naturally.
What's Next
Now learn the Authorization Code Grant — the most secure and widely recommended OAuth2 grant for web applications.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro