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 as `ClientError` in `DigestAuthMiddleware._encode` (client_middleware_digest_auth.py:242-245) when the parsed Digest challenge dict lacks a `realm` key. `realm` is mandatory per RFC 7616 (and RFC 2617) and is required material for every digest hash (H(A1) includes `username:realm:password`). Without it the digest cannot be computed, so the middleware refuses rather than sending an unauthenticated or wrong response.

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 c0ef574e29)

Solutions

  1. Inspect the actual `WWW-Authenticate` header the server sent (capture response headers).
  2. Fix the server to include `realm=` in its Digest challenge (RFC 7616 §3.6).
  3. Confirm the route actually uses Digest auth; if it uses Basic/Bearer, use the appropriate auth mechanism instead.
  4. Catch `ClientError` from the middleware and fall back to a non-digest request or report the misconfiguration.

Example fix

// before
# server sends: WWW-Authenticate: Digest nonce="abc"
# -> missing realm -> ClientError
// after (server-side)
# WWW-Authenticate: Digest realm="myrealm", nonce="abc", qop="auth"
Defensive patterns

Strategy: try-catch

Validate before calling

from aiohttp import hdrs

def challenge_has_realm(resp_headers) -> bool:
    auth = resp_headers.get(hdrs.WWW_AUTHENTICATE, '')
    return 'realm=' in auth.lower()

Try / catch

from aiohttp import ClientError

try:
    resp = await session.get(url, middlewares=[digest_mw])
except ClientError as e:
    if "Missing 'realm'" in str(e):
        log.error('server Digest challenge lacks realm; check WWW-Authenticate')
    raise

Prevention

When it happens

Trigger: Server returns `WWW-Authenticate: Digest` *without* a `realm=` parameter; the challenge is so malformed that the parser (parse_header_pairs) extracted no realm; server returned a different auth scheme whose challenge the middleware mistook for Digest.

Common situations: Server misconfiguration omitting realm; custom/legacy auth server not following RFC; the middleware applied to a route protected by Basic or Bearer auth instead of Digest; challenge was truncated by a proxy.

Related errors


AI-assisted analysis of aio-libs/aiohttp@c0ef574e29 (2026-08-04). Data as JSON: /data/errors/d37509dd59133fc5.json. Report an issue: GitHub.