""" Unit tests for auth classes. Integration tests also exist in tests/client/test_auth.py """ from urllib.request import parse_keqv_list import pytest import httpx def test_basic_auth(): auth = httpx.BasicAuth(username="user", password="pass") request = httpx.Request("GET", "https://www.example.com") # The initial request should include a basic auth header. flow = auth.sync_auth_flow(request) request = next(flow) assert request.headers["Authorization"].startswith("Basic") # No other requests are made. response = httpx.Response(content=b"Hello, world!", status_code=200) with pytest.raises(StopIteration): flow.send(response) def test_digest_auth_with_200(): auth = httpx.DigestAuth(username="user", password="pass") request = httpx.Request("GET", "https://www.example.com") # The initial request should not include an auth header. flow = auth.sync_auth_flow(request) request = next(flow) assert "Authorization" not in request.headers # If a 200 response is returned, then no other requests are made. response = httpx.Response(content=b"Hello, world!", status_code=200) with pytest.raises(StopIteration): flow.send(response) def test_digest_auth_with_401(): auth = httpx.DigestAuth(username="user", password="pass") request = httpx.Request("GET", "https://www.example.com") # The initial request should not include an auth header. flow = auth.sync_auth_flow(request) request = next(flow) assert "Authorization" not in request.headers # If a 401 response is returned, then a digest auth request is made. headers = { "WWW-Authenticate": 'Digest realm="...", qop="auth", nonce="...", opaque="..."' } response = httpx.Response( content=b"Auth required", status_code=401, headers=headers ) request = flow.send(response) assert request.headers["Authorization"].startswith("Digest") # No other requests are made. response = httpx.Response(content=b"Hello, world!", status_code=200) with pytest.raises(StopIteration): flow.send(response) def test_digest_auth_with_401_nonce_counting(): auth = httpx.DigestAuth(username="user", password="pass") request = httpx.Request("GET", "https://www.example.com") # The initial request should not include an auth header. flow = auth.sync_auth_flow(request) request = next(flow) assert "Authorization" not in request.headers # If a 401 response is returned, then a digest auth request is made. headers = { "WWW-Authenticate": 'Digest realm="...", qop="auth", nonce="...", opaque="..."' } response = httpx.Response( content=b"Auth required", status_code=401, headers=headers ) first_request = flow.send(response) assert first_request.headers["Authorization"].startswith("Digest") # Each subsequent request contains the digest header by default... request = httpx.Request("GET", "https://www.example.com") flow = auth.sync_auth_flow(request) second_request = next(flow) assert second_request.headers["Authorization"].startswith("Digest") # ... and the client nonce count (nc) is increased first_nc = parse_keqv_list(first_request.headers["Authorization"].split(", "))["nc"] second_nc = parse_keqv_list(second_request.headers["Authorization"].split(", "))[ "nc" ] assert int(first_nc, 16) + 1 == int(second_nc, 16) # No other requests are made. response = httpx.Response(content=b"Hello, world!", status_code=200) with pytest.raises(StopIteration): flow.send(response)