Skip to content

feat: add RFC 7616 support for non-Latin credentials in HTTPDigestAuth#7232

Open
Jo2234 wants to merge 1 commit intopsf:mainfrom
Jo2234:fix/digest-auth-non-latin-credentials
Open

feat: add RFC 7616 support for non-Latin credentials in HTTPDigestAuth#7232
Jo2234 wants to merge 1 commit intopsf:mainfrom
Jo2234:fix/digest-auth-non-latin-credentials

Conversation

@Jo2234
Copy link

@Jo2234 Jo2234 commented Mar 1, 2026

Summary

Implement RFC 7616 extensions to fix HTTPDigestAuth failing with non-Latin-1 usernames (e.g., Cyrillic, Czech diacritics).

Problem

import requests
from requests.auth import HTTPDigestAuth

# This fails — 'ř' cannot be encoded as latin-1
auth = HTTPDigestAuth('Ondřej', 'heslíčko')
# The Digest header produces: username="Ondřej" which is invalid

# Workaround from issue produces garbled bytes:
auth = HTTPDigestAuth('Ondřej'.encode('utf-8'), 'heslíčko')
# Produces: username="b'Ond\\xc5\\x99ej'"  — wrong!

Solution

This PR implements three RFC 7616 features:

1. username* parameter (RFC 7616 §3.4 + RFC 5987)

When the username cannot be encoded as Latin-1, the username* parameter with RFC 5987 encoding is used:

# Before (broken):
Digest username="Ondřej", ...

# After (correct):
Digest username*=UTF-8''Ond%C5%99ej, ...

2. userhash support (RFC 7616 §3.4.4)

When the server sends userhash=true in the challenge, the username is hashed for privacy:

Digest username="<hash of username:realm>", ..., userhash=true

3. charset echo (RFC 7616 §3.3)

When the server advertises charset=UTF-8, the client echoes it back.

Changes

File Change
src/requests/auth.py Added _is_latin1_encodable(), _encode_rfc5987(), and updated build_digest_header() with RFC 7616 username handling
tests/test_digest_rfc7616.py 12 new tests covering: Latin-1 detection, RFC 5987 encoding, username* parameter, userhash, charset, and response digest validity

Backward Compatibility

  • Latin-1 encodable usernames (ASCII, Western European): No change in behavior — the standard username="..." parameter is used as before
  • Non-Latin-1 usernames (Cyrillic, CJK, etc.): Now work correctly instead of failing
  • The response digest computation is unchanged — A1 = username:realm:password is still hashed with UTF-8

Fixes #6102

HTTPDigestAuth currently fails when usernames contain non-Latin-1
characters (e.g., Cyrillic, Czech diacritics). The username is
directly interpolated into the Digest header, which either produces
garbled output or raises a UnicodeEncodeError.

This commit implements RFC 7616 (HTTP Digest Access Authentication)
extensions to properly handle non-Latin credentials:

1. username* parameter (RFC 7616 Section 3.4 + RFC 5987):
   When the username contains characters outside Latin-1, the
   username* parameter with RFC 5987 encoding is used instead of
   the standard username parameter.
   Format: username*=UTF-8''percent-encoded-value

2. userhash support (RFC 7616 Section 3.4.4):
   When the server sends userhash=true in the WWW-Authenticate
   challenge, the client hashes the username with the realm using
   the selected hash algorithm, providing privacy protection.

3. charset support (RFC 7616 Section 3.3):
   When the server advertises charset=UTF-8, the client echoes it
   back in the Authorization header.

The fix also adds:
- _is_latin1_encodable() helper to detect non-Latin-1 strings
- _encode_rfc5987() helper for RFC 5987 encoding
- Comprehensive test suite in tests/test_digest_rfc7616.py

Fixes psf#6102
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTTPDigestAuth fails on non-latin credentials

1 participant