🔐 OWASP API Security

API2:2023 - Broken User Authentication

📋 Overview

Broken User Authentication represents one of the most critical vulnerabilities in modern API security. This vulnerability occurs when authentication mechanisms are incorrectly implemented, allowing attackers to compromise passwords, keys, session tokens, or exploit implementation flaws to assume other users' identities.

⚠️ Critical Risk

This vulnerability can easily lead to complete account takeover. In today's microservices architecture with numerous micro APIs communicating with each other, it's extremely easy to overlook authentication endpoints, making this a widespread and dangerous vulnerability.

🎯 Why This Matters

Implementing authentication correctly is challenging. Many developers and architects struggle with determining what to include in authentication controls. Modern software consists of multiple micro APIs - small servers with specific functionality that constantly communicate with each other. This complexity makes it easy to overlook critical endpoints.

🔍 Common Vulnerabilities

  • Credential Stuffing: The API allows brute force attacks without implementing account lockout mechanisms after multiple failed attempts
  • Missing CAPTCHA Verification: API endpoints that don't verify CAPTCHA requests, making automated attacks trivial
  • Sensitive Data in GET Parameters: Using GET parameters for authentication data, even over HTTPS, poses risks if accidentally sent over HTTP
  • Unverified JWT Tokens: The endpoint issues JWT tokens but never validates them, relying instead on parameters like user_id
  • Weak JWT Signing: Servers accepting JWT tokens signed with insecure algorithms (like 'none')
  • Expired Token Acceptance: Endpoints that don't properly validate token expiration dates
  • Weak Keys: Using easily guessable or crackable encryption keys (e.g., MD5 hashing)

💡 Attack Scenarios

Scenario 1: Password Reset Attack

Attack Flow:

Password Reset Brute Force Attack
1. Attacker Requests
Password Reset
2. System Generates
4-Digit Token
3. Attacker Brute Forces
0000-9999
4. Account
Compromised

Initial Request:

POST /api/reset-password?user_id=1234

System Response:

Email sent to user with token: token_id=XXXX

Attack Execution:

POST /api/validate-reset?user_id=1234&token_id=0000 POST /api/validate-reset?user_id=1234&token_id=0001 POST /api/validate-reset?user_id=1234&token_id=0002 ... (continues through 9999)

The Problem: Without rate limiting, an attacker can rapidly test all 10,000 possible combinations. With modern computing power, this takes only seconds.

Scenario 2: JWT Algorithm Confusion Attack

JWT Token Manipulation
1. User Receives
Valid JWT Token
2. Attacker Decodes
JWT Payload
3. Modifies User Data
& Re-signs with 'none'
4. Server Accepts
Forged Token

Original JWT Token:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMTIzIiwicm9sZSI6InVzZXIifQ.signature

Decoded Payload:

{ "alg": "HS256", "typ": "JWT" } { "user_id": "123", "role": "user" }

Manipulated Token (Algorithm changed to 'none'):

eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJ1c2VyX2lkIjoiMSIsInJvbGUiOiJhZG1pbiJ9.

Manipulated Payload:

{ "alg": "none", "typ": "JWT" } { "user_id": "1", "role": "admin" }

The Problem: If the server accepts tokens signed with the 'none' algorithm, attackers can forge tokens and impersonate any user, including administrators.

🛡️ Prevention Measures

1. Map All Authentication Flows

Document every authentication flow in your system:

  • Mobile applications and deep links
  • Desktop applications
  • IoT devices
  • Email-based authentication
  • Third-party integrations
  • API-to-API authentication

Best Practice: Create flow diagrams and explain them to team members to identify knowledge gaps.

2. Use Established Authentication Mechanisms

DO NOT implement your own authentication mechanism!

Use well-tested, industry-standard authentication frameworks. These have been battle-tested and reviewed by security experts worldwide. Don't reinvent the wheel.

Recommended Resource:

Reference: OWASP Authentication Cheat Sheet URL: https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html

3. Implement Rate Limiting

All authentication endpoints MUST have strict rate limiting:

  • Login endpoints
  • Password reset endpoints
  • Token refresh endpoints
  • Account recovery endpoints

Implementation Example:

// Lock account after 5 failed attempts if (failedAttempts >= 5) { lockAccount(userId, duration: 15 minutes); sendAlertEmail(userId); } // Implement exponential backoff waitTime = Math.pow(2, failedAttempts) * 1000; // milliseconds

Rate limiting must be MORE STRICT on authentication endpoints than regular API endpoints.

4. Implement Multi-Factor Authentication (MFA)

Always implement true multi-factor authentication:

✅ Valid MFA Combinations:

  • Password + Authenticator App (Google Authenticator, Authy)
  • Password + Hardware Token (YubiKey)
  • Password + Biometric
  • Password + SMS (less secure, but better than nothing)

❌ Invalid MFA Combinations:

  • Two passwords
  • Password + Email verification (email may be compromised)
  • Password + Security questions

Key Principle: Assume the user's primary credentials are already compromised. MFA should require a separate, independent authentication factor.

5. Implement CAPTCHA Mechanisms

Deploy CAPTCHA on all sensitive endpoints:

  • Login pages
  • Registration pages
  • Password reset pages
  • Any endpoint susceptible to automation

Implementation Options:

Google reCAPTCHA v3 (invisible, risk-based) hCaptcha (privacy-focused alternative) Custom CAPTCHA (for specialized requirements)

6. Proper API Key Usage

Important Distinction:

❌ DO NOT use API keys for USER authentication

✅ DO use API keys for CLIENT APP authentication

Correct Usage:

// API Key for client app identification headers: { 'X-API-Key': 'app_client_key_12345', 'Authorization': 'Bearer user_jwt_token_xyz' }

API keys identify which application is making the request, while user tokens (like JWT) authenticate the actual user. Never confuse these two purposes.

7. JWT Best Practices

  • Always validate JWT signatures - Never trust unsigned tokens
  • Reject 'none' algorithm - Explicitly block this in your validation
  • Verify token expiration - Check 'exp' claim on every request
  • Use strong signing algorithms - RS256 or HS256 with strong keys
  • Implement token refresh - Short-lived access tokens with refresh mechanism
  • Store tokens securely - Use HttpOnly cookies or secure storage

Validation Example:

function validateJWT(token) { // 1. Verify signature if (!verifySignature(token)) return false; // 2. Check algorithm const header = decodeHeader(token); if (header.alg === 'none') return false; // 3. Verify expiration const payload = decodePayload(token); if (payload.exp < Date.now() / 1000) return false; // 4. Additional checks (issuer, audience, etc.) if (payload.iss !=='your-api.com' ) return false; return true; }

🔧 Testing Commands

Testing for Rate Limiting

Using cURL to test brute force protection:

for i in {1..100}; do curl -X POST https://api.example.com/login -d "username=test&password=wrong$i"; done

Expected behavior: Account should lock after configured attempts (e.g., 5)

Testing JWT Validation

Decode JWT token:

echo "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoiMTIzIn0.signature" | base64 -d

Test 'none' algorithm vulnerability:

curl -X GET https://api.example.com/profile -H "Authorization: Bearer eyJhbGciOiJub25lIn0.eyJ1c2VyX2lkIjoiMSJ9."

Expected behavior: Server should reject tokens with 'none' algorithm

Testing Password Reset Vulnerabilities

Request password reset:

curl -X POST https://api.example.com/reset-password -d "[email protected]"

Attempt token brute force:

for token in {0000..9999}; do curl -X POST https://api.example.com/validate-reset -d "[email protected]&token=$token"; done

Expected behavior: Rate limiting should block rapid token validation attempts

📊 Impact Assessment

Attack Impact Scale
🔴 Critical: Complete account takeover, admin access compromise
🟡 High: User impersonation, unauthorized data access
🟢 Medium: Session hijacking, limited unauthorized access

🎓 Key Takeaways

  • Never underestimate authentication complexity - It's harder than it looks
  • Use proven solutions - Don't create custom authentication in weekend projects
  • Layer your defenses - Rate limiting, CAPTCHA, MFA, and proper validation all work together
  • Assume breach - Design systems assuming user credentials are already compromised
  • Test thoroughly - Authentication endpoints require more rigorous testing than regular APIs
  • Stay updated - New attack vectors emerge regularly; keep authentication mechanisms current
  • Documentation matters - Map all flows and ensure team understanding

⚠️ Final Warning

Prevention is NOT the same as stopping attacks. A determined attacker will find ways around defenses. The goal is to make attacks:

  • Extremely difficult and time-consuming
  • Easily detectable through monitoring
  • Limited in scope if successful

Always stay one step ahead by continuously updating your security measures and monitoring for suspicious activity.

📚 Additional Resources

  • OWASP Authentication Cheat Sheet: Comprehensive guide for secure authentication implementation
  • OAuth 2.0 Security Best Practices: Essential reading for OAuth implementations
  • JWT.io: Tool for debugging and understanding JWT tokens
  • OWASP API Security Top 10: Complete list of API security risks