Skip to content

Authentication Errors

DodaTech 2 min read

title: "Authentication Errors — Handling Missing and Invalid Credentials" description: "API authentication errors return 401 for missing/invalid credentials and 403 for valid but insufficient permissions, with clear messages about required auth methods." date: 2026-06-28 lastmod: 2026-06-28 weight: 15 tags: [apis, error-handling] }

Authentication errors occur when a client fails to prove their identity, requiring 401 Unauthorized for missing/invalid credentials and 403 Forbidden for insufficient permissions.

What You'll Learn

  • Distinguishing 401 from 403 errors
  • Common authentication failure patterns
  • Secure error messages that don't aid attackers

Why It Matters

Authentication errors are common but sensitive. Too much information helps attackers; too little frustrates legitimate developers.

flowchart TD
    A["Client Request"] --> B{"Has Auth?"}
    B -->|"No"| C["401 + WWW-Authenticate"]
    B -->|"Yes"| D{"Credentials Valid?"}
    D -->|"No"| E["401 + Invalid credentials"]
    D -->|"Yes"| F{"Has Permission?"}
    F -->|"No"| G["403 + Insufficient scope"]
    F -->|"Yes"| H["200 OK - Process request"]
    style B fill:#dbeafe,stroke:#2563eb

Code Examples

# Authentication error responses
@app.errorhandler(401)
def unauthorized(error):
    return jsonify({
        "error": "UNAUTHORIZED",
        "message": "Authentication required",
        "auth_url": "https://docs.example.com/auth"
    }), 401, {"WWW-Authenticate": "Bearer"}

@app.errorhandler(403)
def forbidden(error):
    return jsonify({
        "error": "FORBIDDEN",
        "message": "You don't have permission to access this resource",
        "required_scope": error.description.get("scope", "admin")
    }), 403
// Express auth error middleware
function authError(err, req, res, next) {
  if (err.name === 'UnauthorizedError') {
    return res.status(401).json({
      error: 'UNAUTHORIZED',
      message: 'Invalid or expired token',
      code: 'TOKEN_EXPIRED'
    });
  }
  if (err.name === 'ForbiddenError') {
    return res.status(403).json({
      error: 'FORBIDDEN',
      message: `Required scope: ${err.requiredScope}`,
      required_scope: err.requiredScope
    });
  }
  next(err);
}

Common Mistakes

1. Returning 403 Instead of 401

Use 401 when no/invalid auth; 403 when auth is valid but not enough.

2. Revealing Whether User Exists

"Invalid username" or "Invalid password" separately helps attackers enumerate users.

3. Not Including WWW-Authenticate Header

The WWW-Authenticate header tells clients which auth scheme to use.

4. Expired Token Without Clear Code

Return a specific error code like TOKEN_EXPIRED so clients can refresh.

5. No Auth Documentation in Error Response

Include a link to auth documentation so developers know what to do.

Practice Questions

  1. What is the difference between 401 and 403?
  2. Why should you avoid distinguishing "user not found" from "wrong password"?
  3. What is the purpose of the WWW-Authenticate header?
  4. How should expired tokens be communicated?
  5. Why include a link to auth documentation in errors?

Answers:

  1. 401 means no/invalid credentials; 403 means valid credentials but insufficient permissions.
  2. Attackers can enumerate valid usernames.
  3. It tells the client what authentication scheme to use (Bearer, Basic, Digest).
  4. With a specific error code like TOKEN_EXPIRED and a refresh endpoint URL.
  5. So developers can quickly find how to authenticate correctly.

Challenge: Design an auth error handling system that returns 401 for expired tokens, 403 for insufficient scopes, and 401 with WWW-Authenticate for missing credentials.

FAQ

Should I return 401 or 403 when the API key format is wrong?

: 401. The credentials are invalid or malformed.

What status code is used for expired API keys?

: 401. The credentials are no longer valid.

Can I return 402 Payment Required for auth?

: No. 402 is reserved for future use. Use 403 for subscription issues.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro