(monkeypatch)
| 249 | |
| 250 | |
| 251 | def test_digest_auth_rfc_7616_sha_256(monkeypatch): |
| 252 | # Example from https://datatracker.ietf.org/doc/html/rfc7616#section-3.9.1 |
| 253 | |
| 254 | def mock_get_client_nonce(nonce_count: int, nonce: bytes) -> bytes: |
| 255 | return "f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ".encode() |
| 256 | |
| 257 | auth = httpx.DigestAuth(username="Mufasa", password="Circle of Life") |
| 258 | monkeypatch.setattr(auth, "_get_client_nonce", mock_get_client_nonce) |
| 259 | |
| 260 | request = httpx.Request("GET", "https://www.example.com/dir/index.html") |
| 261 | |
| 262 | # The initial request should not include an auth header. |
| 263 | flow = auth.sync_auth_flow(request) |
| 264 | request = next(flow) |
| 265 | assert "Authorization" not in request.headers |
| 266 | |
| 267 | # If a 401 response is returned, then a digest auth request is made. |
| 268 | headers = { |
| 269 | "WWW-Authenticate": ( |
| 270 | 'Digest realm="http-auth@example.org", ' |
| 271 | 'qop="auth, auth-int", ' |
| 272 | "algorithm=SHA-256, " |
| 273 | 'nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v", ' |
| 274 | 'opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"' |
| 275 | ) |
| 276 | } |
| 277 | response = httpx.Response( |
| 278 | content=b"Auth required", status_code=401, headers=headers, request=request |
| 279 | ) |
| 280 | request = flow.send(response) |
| 281 | assert request.headers["Authorization"].startswith("Digest") |
| 282 | assert 'username="Mufasa"' in request.headers["Authorization"] |
| 283 | assert 'realm="http-auth@example.org"' in request.headers["Authorization"] |
| 284 | assert 'uri="/dir/index.html"' in request.headers["Authorization"] |
| 285 | assert "algorithm=SHA-256" in request.headers["Authorization"] |
| 286 | assert ( |
| 287 | 'nonce="7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v"' |
| 288 | in request.headers["Authorization"] |
| 289 | ) |
| 290 | assert "nc=00000001" in request.headers["Authorization"] |
| 291 | assert ( |
| 292 | 'cnonce="f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ"' |
| 293 | in request.headers["Authorization"] |
| 294 | ) |
| 295 | assert "qop=auth" in request.headers["Authorization"] |
| 296 | assert ( |
| 297 | 'opaque="FQhe/qaU925kfnzjCev0ciny7QMkPqMAFRtzCUYo5tdS"' |
| 298 | in request.headers["Authorization"] |
| 299 | ) |
| 300 | assert ( |
| 301 | 'response="753927fa0e85d155564e2e272a28d1802ca10daf4496794697cf8db5856cb6c1"' |
| 302 | in request.headers["Authorization"] |
| 303 | ) |
| 304 | |
| 305 | # No other requests are made. |
| 306 | response = httpx.Response(content=b"Hello, world!", status_code=200) |
| 307 | with pytest.raises(StopIteration): |
| 308 | flow.send(response) |
nothing calls this directly
no test coverage detected