- Home
- HTTP Headers
- WWW-Authenticate
Header
WWW-Authenticate
Learn how the WWW-Authenticate header specifies authentication methods required to access protected resources. Understand Basic, Bearer, and Digest schemes.
TL;DR: Sent with 401 responses to specify required authentication method (Basic, Bearer, Digest). Tells clients how to provide credentials for protected resources.
What is WWW-Authenticate?
WWW-Authenticate tells the client what authentication method is required to access a protected resource. It’s like a bouncer at a club saying “you need to show ID and be on the guest list” - it specifies exactly what credentials are needed and how to provide them.
This header is sent with 401 Unauthorized responses to guide clients on how to authenticate.
How It Works
1. Client requests protected resource:
GET /admin/dashboard HTTP/1.1
Host: example.com
```text
**2. Server responds with authentication challenge:**
```http
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Admin Area"
Content-Type: text/html
<h1>401 Unauthorized</h1>
<p>Please provide valid credentials.</p>
3. Client prompts user for credentials and retries:
GET /admin/dashboard HTTP/1.1
Authorization: Basic dXNlcjpwYXNzd29yZA==
```text
**4. Server validates and responds** with the protected resource.
## Authentication Schemes
### Basic Authentication
Simple username/password authentication:
```http
WWW-Authenticate: Basic realm="Protected Area"
Client encodes credentials in Base64:
Authorization: Basic dXNlcjpwYXNzd29yZA==
```text
(Decodes to `user:password`)
### Bearer Token
Token-based authentication (JWT, API keys):
```http
WWW-Authenticate: Bearer realm="API Access"
Client sends token:
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```text
### Digest Authentication
More secure than Basic (password not sent in plain text):
```http
WWW-Authenticate: Digest realm="Protected", qop="auth", nonce="dcd98b7102dd2f0e8b11d0f600bfb0c093", opaque="5ccc069c403ebaf9f0171e9517f40e41"
Custom Schemes
API-specific authentication methods:
WWW-Authenticate: ApiKey realm="API v1"
WWW-Authenticate: OAuth realm="OAuth 2.0"
```http
## Realm Parameter
The `realm` describes the protected area:
```http
WWW-Authenticate: Basic realm="Admin Panel"
WWW-Authenticate: Basic realm="User Dashboard"
WWW-Authenticate: Basic realm="Financial Data"
Browsers often display the realm in authentication dialogs.
Multiple Authentication Options
Offer multiple authentication methods:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Protected Area"
WWW-Authenticate: Bearer realm="API Access"
WWW-Authenticate: Digest realm="Secure Zone"
```text
Client can choose which method to use.
## Real-World Examples
### API Authentication
```http
GET /api/users HTTP/1.1
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="API v2", error="invalid_token", error_description="The access token expired"
Content-Type: application/json
{
"error": "unauthorized",
"message": "Valid bearer token required"
}
Admin Panel
GET /admin HTTP/1.1
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Administration"
Content-Type: text/html
<!DOCTYPE html>
<html>
<head><title>401 Unauthorized</title></head>
<body>
<h1>Authentication Required</h1>
<p>Please log in to access the admin panel.</p>
</body>
</html>
```text
### OAuth 2.0 API
```http
GET /api/profile HTTP/1.1
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer realm="OAuth 2.0", error="invalid_token", error_description="Token has expired"
Content-Type: application/json
{
"error": "token_expired",
"message": "Please refresh your access token"
}
File Server
GET /private/documents/report.pdf HTTP/1.1
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Basic realm="Document Server"
Content-Type: text/plain
Authentication required to access private documents.
```text
## OAuth 2.0 Error Parameters
For Bearer token authentication, include error details:
```http
WWW-Authenticate: Bearer realm="API", error="invalid_token", error_description="The token is malformed"
Common error codes:
invalid_request- Request is malformedinvalid_token- Token is invalid or expiredinsufficient_scope- Token lacks required permissions
Server Implementation
Express.js Basic Auth
app.get('/protected', (req, res) => {
const auth = req.headers.authorization
if (!auth || !auth.startsWith('Basic ')) {
res.set('WWW-Authenticate', 'Basic realm="Protected Area"')
return res.status(401).json({
error: 'Authentication required',
message: 'Please provide valid credentials'
})
}
const credentials = Buffer.from(auth.slice(6), 'base64').toString()
const [username, password] = credentials.split(':')
if (!validateCredentials(username, password)) {
res.set('WWW-Authenticate', 'Basic realm="Protected Area"')
return res.status(401).json({
error: 'Invalid credentials'
})
}
res.json({ message: 'Access granted' })
})
```javascript
### Express.js Bearer Token
```javascript
app.get('/api/data', (req, res) => {
const auth = req.headers.authorization
if (!auth || !auth.startsWith('Bearer ')) {
res.set('WWW-Authenticate', 'Bearer realm="API v1"')
return res.status(401).json({
error: 'token_required',
message: 'Bearer token required'
})
}
const token = auth.slice(7)
try {
const decoded = jwt.verify(token, process.env.JWT_SECRET)
res.json({ data: 'Protected data', user: decoded.sub })
} catch (error) {
res.set(
'WWW-Authenticate',
'Bearer realm="API v1", error="invalid_token", error_description="Token is invalid or expired"'
)
return res.status(401).json({
error: 'invalid_token',
message: 'Token is invalid or expired'
})
}
})
Python Flask
from flask import Flask, request, jsonify
import base64
@app.route('/protected')
def protected():
auth = request.headers.get('Authorization')
if not auth or not auth.startswith('Basic '):
response = jsonify({'error': 'Authentication required'})
response.status_code = 401
response.headers['WWW-Authenticate'] = 'Basic realm="Protected Area"'
return response
credentials = base64.b64decode(auth[6:]).decode('utf-8')
username, password = credentials.split(':', 1)
if not validate_credentials(username, password):
response = jsonify({'error': 'Invalid credentials'})
response.status_code = 401
response.headers['WWW-Authenticate'] = 'Basic realm="Protected Area"'
return response
return jsonify({'message': 'Access granted'})
```text
## Security Considerations
### Basic Authentication Risks
```http
❌ Over HTTP (credentials visible):
WWW-Authenticate: Basic realm="Admin"
✅ Over HTTPS only:
WWW-Authenticate: Basic realm="Admin"
# + Strict-Transport-Security header
Token Security
✅ Include error details for debugging:
WWW-Authenticate: Bearer realm="API", error="invalid_token", error_description="Token expired at 2025-01-15T10:30:00Z"
```text
### Realm Information Disclosure
```http
❌ Too much information:
WWW-Authenticate: Basic realm="Internal Admin Database Server #3"
✅ Generic but helpful:
WWW-Authenticate: Basic realm="Admin Area"
Best Practices
1. Always use HTTPS with Basic authentication:
WWW-Authenticate: Basic realm="Secure Area"
# Only over HTTPS connections
```http
**2. Provide helpful realm descriptions:**
```http
WWW-Authenticate: Basic realm="Customer Portal"
WWW-Authenticate: Bearer realm="API v2"
3. Include error details for APIs:
WWW-Authenticate: Bearer realm="API", error="insufficient_scope", error_description="Token lacks 'admin' scope"
```http
**4. Support multiple authentication methods:**
```http
WWW-Authenticate: Basic realm="Legacy Support"
WWW-Authenticate: Bearer realm="Modern API"
5. Use appropriate status codes:
401 Unauthorized + WWW-Authenticate # Authentication required
403 Forbidden # Authenticated but not authorized
Related Headers
- Authorization - Request header containing credentials
- Proxy-Authenticate - Proxy authentication challenge
- Authentication-Info - Additional auth information
- Set-Cookie - Alternative session-based authentication
Frequently Asked Questions
What is WWW-Authenticate?
WWW-Authenticate is sent with 401 responses to tell clients how to authenticate. It specifies the authentication scheme (Basic, Bearer, Digest) and parameters like realm.
What authentication schemes are common?
Basic (username:password base64), Bearer (OAuth tokens), and Digest (hashed credentials) are most common. Bearer is standard for modern APIs with JWT or OAuth.
What is the realm parameter?
Realm describes the protected area. Browsers may show it in login prompts. Use descriptive names like "Admin Area" or "API Access" to help users understand what credentials to use.
Can I use multiple authentication schemes?
Yes, send multiple WWW-Authenticate headers to offer different methods. Clients choose their preferred scheme. List preferred schemes first.