aio-libs/aiohttp · error · ClientError
Malformed Digest auth challenge: Missing 'realm' parameter
Error message
Malformed Digest auth challenge: Missing 'realm' parameter
What it means
Raised by aiohttp's Digest auth middleware when a server's WWW-Authenticate Digest challenge omits the required 'realm' parameter. RFC 7616 mandates realm in every Digest challenge, so aiohttp refuses to build an authorization header without it and raises ClientError. The error surfaces during the middleware's response-challenge handling, after a 401 is received and the cached challenge dict is inspected in _encode().
Solutions
- Inspect the raw response headers (use a plain aiohttp request without the middleware) to confirm the server's WWW-Authenticate value is missing realm.
- Fix the server / proxy configuration so the Digest challenge includes realm (e.g. 'WWW-Authenticate: Digest realm="myhost", nonce=...').
- If you cannot change the server, drop DigestAuthMiddleware for that endpoint and handle auth manually or use Basic auth.
- Verify no intermediary (CDN, gateway) is rewriting or stripping the WWW-Authenticate header.
Example fix
# before
app = DigestAuthMiddleware(login='u', password='p')
await session.get('https://bad-server/digest') # server omits realm
# after — confirm the challenge first
resp = await session.get('https://bad-server/digest')
print(resp.headers.get('WWW-Authenticate'))
# then fix the server to send: Digest realm="myhost", nonce="..." Defensive patterns
Strategy: try-catch
Validate before calling
# Before using digest middleware, probe the challenge
async def get_challenge(session, url):
resp = await session.get(url)
wa = resp.headers.get('WWW-Authenticate', '')
await resp.release()
return wa
# check the header contains realm=
challenge = await get_challenge(session, url)
if 'realm=' not in challenge.lower():
raise RuntimeError(f'Server Digest challenge missing realm: {challenge}') Type guard
def has_realm(www_authenticate_header: str) -> bool:
return 'realm=' in www_authenticate_header.lower() Try / catch
from aiohttp import ClientError
try:
async with session.get(url, headers=mw_headers) as resp:
...
except ClientError as e:
if 'realm' in str(e):
log.error('Digest challenge malformed (no realm); check server WWW-Authenticate')
# fall back to non-digest auth or surface to user
raise Prevention
- Always inspect the raw WWW-Authenticate header before relying on Digest middleware.
- Maintain a server-configuration checklist that requires realm + nonce in Digest challenges.
- In CI, run a smoke test against the real auth endpoint to catch regressions early.
When it happens
Trigger: Configuring a DigestAuthMiddleware (or TraceConfig-based digest client) and sending a request to a server that returns 'WWW-Authenticate: Digest' with no realm parameter (e.g. 'WWW-Authenticate: Digest nonce=abc'). The error fires when aiohttp attempts to compute the Authorization header from that incomplete challenge.
Common situations: Misconfigured or non-compliant reverse proxy / origin server omitting realm; home-grown test servers returning a hand-crafted Digest header; proxies that strip or rewrite WWW-Authenticate; connecting through an intermediary that mangles the challenge.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Digest auth error: Unsupported hash algorithm
- Digest auth error: Unsupported Quality of Protection (qop)…
- Malformed Digest auth challenge: Missing 'nonce' parameter
- Security issue: Digest auth challenge contains empty…
- A ":" is not allowed in username (RFC 1945#section-11.1)
AI-assisted analysis of aio-libs/aiohttp@d041d4d0fd (2026-08-11).
Data as JSON: /api/errors/d37509dd59133fc5.
Report an issue: GitHub.
Appendix: source
Thrown at aiohttp/client_middleware_digest_auth.py:243
"""
Build digest authorization header for the current challenge.
Args:
method: The HTTP method (GET, POST, etc.)
url: The request URL
body: The request body (used for qop=auth-int)
Returns:
A fully formatted Digest authorization header string
Raises:
ClientError: If the challenge is missing required parameters or
contains unsupported values
"""
challenge = self._challenge
if "realm" not in challenge:
raise ClientError(
"Malformed Digest auth challenge: Missing 'realm' parameter"
)
if "nonce" not in challenge:
raise ClientError(
"Malformed Digest auth challenge: Missing 'nonce' parameter"
)
# Empty realm values are allowed per RFC 7616 (SHOULD, not MUST, contain host name)
realm = challenge["realm"]
nonce = challenge["nonce"]
# Empty nonce values are not allowed as they are security-critical for replay protection
if not nonce:
raise ClientError(
"Security issue: Digest auth challenge contains empty 'nonce' value"
)
View on GitHub (pinned to d041d4d0fd)