An Extension to HTTP : Digest Access Authentication
obsoleted by
- rfc-2617 — HTTP Authentication: Basic and Digest Access Authentication
Extracted elements (25)
Digest Access Authentication was created solely to replace Basic Authentication, which transmits passwords in cleartext. It is intentionally a weak mechanism — not a complete security solution — providing no content encryption and being weaker than Kerberos or client-side private-key schemes. An important design constraint was that the scheme be free of patent and export restrictions.
Including the realm in A1 (and therefore in the stored H(A1)) means that compromise of one realm's password file does not automatically compromise other realms sharing the same username and password, though it still exposes them to brute-force attack. This is why the realm string should be globally unique and include the authenticating hostname.
The server does not need to store the user's cleartext password: authentication can be verified as long as H(A1) = MD5(username:realm:password) is available. This allows storing only a derived value while fully authenticating clients.
The authenticating server must verify that the document identified by the uri parameter in the Authorization header is the same as the document actually served, since an intermediate proxy may have altered the original Request-URI. A mismatch should cause the server to reject the request.
A shared cache that has received a request containing an Authorization header MUST NOT return that response to any other request, unless the response included a must-revalidate or public Cache-Control directive.
If the nextnonce field is present in Authentication-info, the client is strongly encouraged to use it for the next request. Failure to do so may result in a 401 re-authentication challenge with stale=TRUE.
Proxies MUST be completely transparent in Digest authentication, forwarding WWW-Authenticate, Authentication-info, and Authorization headers untouched. Proxy-level authentication uses separate Proxy-Authenticate and Proxy-Authorization headers.
The server SHOULD only set stale=TRUE if it receives a request with an invalid (expired) nonce but whose digest is valid for that nonce, confirming the client knows the correct credentials.
The uri field in the Authorization header MUST agree with the Request-URI. In particular, it MUST be an absoluteURL if the Request-URI is an absoluteURL.
Proxy authentication uses Proxy-Authenticate (carrying digest-challenge) and Proxy-Authorization (carrying digest-response) with the same structure as server authentication. A client that receives both WWW-Authenticate and Proxy-Authenticate challenges must respond with both Authorization and Proxy-Authorization headers, typically with different credentials.
The Authentication-info response header optionally carries two fields: digest (entity-digest of the response for integrity verification) and nextnonce (the nonce the server wants the client to use for the next request, enabling one-time nonce schemes).
The Authorization request header carries the digest-response with username, realm, nonce, uri, and response fields. The uri field duplicates the Request-URI to allow the server to detect proxy alteration of the original request.
The nonce is a server-specified quoted-string, recommended to be base64 or hexadecimal data. The recommended construction is H(client-IP ":" timestamp ":" private-key), binding the nonce to the requesting IP and a validity window without requiring server state between transactions.
The opaque field is a server-specified, client-echoed quoted-string (recommended base64 or hex) useful for transporting server state across authentication transactions, such as when authenticating content hosted on a second server.
The stale flag in WWW-Authenticate signals that the previous request failed because the nonce was stale, not because the credentials were wrong. When stale=TRUE, the client may retry with a freshly computed digest without reprompting the user for credentials.
The WWW-Authenticate response header carries a digest-challenge with required realm and nonce fields and optional domain, opaque, stale, and algorithm fields. The server sends this alongside a 401 Unauthorized response when no acceptable Authorization header is present.
An attacker can remove or alter the digest field in Authentication-info, preventing the client from using it to detect response-entity modification. Sensitive applications may wish to require the digest field to be present and valid.
Both Digest and Basic authentication are vulnerable to man-in-the-middle attacks from hostile or compromised proxies. A simple effective attack is to replace the Digest challenge with a Basic challenge, coercing the client to reveal its password. Clients should remember if a site has previously used Digest and warn the user if it reverts to Basic.
Digest Authentication eliminates the most dangerous weakness of Basic — password exposure to network eavesdroppers — but an intercepted digest may still be used in a replay attack against the exact same URI. For GET requests a replay is usually pointless; for POST and PUT it can cause counterfeit actions.
Digest Authentication reduces counterfeit-server risk compared to Basic, but clients must be configured to demand Digest and refuse Basic downgrade to be fully protected.
Replay attacks against POST and PUT requests can result in counterfeit form data or files. One-time nonces or digests are recommended for these methods, and the optional entity-digest field should be used to ensure posted data integrity. Alternatively, servers may restrict Digest authentication to GET only.
The server password file stores H(A1) = MD5(username:realm:password) and must be protected as if it contained plaintext passwords, because it grants direct realm access without decryption. A brute-force attack would still be required to recover the actual password.
An MD5 digest of 128 bits is represented as 32 lowercase ASCII hexadecimal characters (0–9, a–f), converting bits from most significant to least significant, four bits at a time.
The optional entity-digest field is KD(H(A1), nonce ":" Method ":" date ":" entity-info ":" H(entity-body)), where entity-info = H(uri ":" content-type ":" content-length ":" content-encoding ":" last-modified ":" expires). Missing fields are left empty but colons are retained.
The response-digest is KD(H(A1), nonce ":" H(A2)), where A1 = username ":" realm ":" password and A2 = Method ":" digest-uri-value. H() defaults to MD5; KD(secret, data) = H(secret ":" data). No surrounding whitespace is allowed around colons in digested strings.