0
# Authentication API
1
2
Authentication mechanisms for HTTP requests including Basic, Digest, custom authentication, and .netrc file support.
3
4
## Overview
5
6
httpx provides several built-in authentication classes and a base class for implementing custom authentication schemes. Authentication can be configured per request or as a default for a client.
7
8
## Capabilities
9
10
### Base Auth Class
11
12
```python { .api }
13
class Auth:
14
"""
15
Base class for authentication schemes.
16
17
Attributes:
18
requires_request_body (bool): Whether auth needs request body
19
requires_response_body (bool): Whether auth needs response body
20
"""
21
22
def auth_flow(self, request):
23
"""
24
Main authentication flow generator.
25
26
Args:
27
request (Request): Request to authenticate
28
29
Yields:
30
Request: Modified request with authentication
31
32
Returns:
33
Response: Final response after authentication
34
"""
35
36
def sync_auth_flow(self, request):
37
"""
38
Synchronous authentication flow generator.
39
40
Args:
41
request (Request): Request to authenticate
42
43
Yields:
44
Request: Modified request with authentication
45
46
Returns:
47
Response: Final response after authentication
48
"""
49
50
async def async_auth_flow(self, request):
51
"""
52
Asynchronous authentication flow generator.
53
54
Args:
55
request (Request): Request to authenticate
56
57
Yields:
58
Request: Modified request with authentication
59
60
Returns:
61
Response: Final response after authentication
62
"""
63
```
64
65
### Basic Authentication
66
67
```python { .api }
68
class BasicAuth(Auth):
69
"""
70
HTTP Basic authentication scheme.
71
72
Encodes credentials as base64 and adds Authorization header.
73
"""
74
75
def __init__(self, username, password):
76
"""
77
Initialize Basic authentication.
78
79
Args:
80
username (str | bytes): Username for authentication
81
password (str | bytes): Password for authentication
82
"""
83
```
84
85
### Digest Authentication
86
87
```python { .api }
88
class DigestAuth(Auth):
89
"""
90
HTTP Digest authentication scheme.
91
92
Implements RFC 7616 HTTP Digest Access Authentication.
93
Supports MD5, SHA-256, SHA-512 algorithms and session variants.
94
"""
95
96
def __init__(self, username, password):
97
"""
98
Initialize Digest authentication.
99
100
Args:
101
username (str | bytes): Username for authentication
102
password (str | bytes): Password for authentication
103
104
Supported algorithms:
105
- MD5, MD5-SESS
106
- SHA, SHA-SESS
107
- SHA-256, SHA-256-SESS
108
- SHA-512, SHA-512-SESS
109
"""
110
```
111
112
### NetRC Authentication
113
114
```python { .api }
115
class NetRCAuth(Auth):
116
"""
117
Authentication using .netrc file credentials.
118
119
Reads credentials from .netrc file based on hostname.
120
Falls back to Basic authentication if credentials found.
121
"""
122
123
def __init__(self, file=None):
124
"""
125
Initialize .netrc authentication.
126
127
Args:
128
file (str, optional): Path to .netrc file (default: ~/.netrc)
129
"""
130
```
131
132
## Usage Examples
133
134
### Basic Authentication
135
136
```python
137
import httpx
138
139
# With top-level functions
140
auth = httpx.BasicAuth('username', 'password')
141
response = httpx.get('https://httpbin.org/basic-auth/username/password', auth=auth)
142
143
# With client
144
with httpx.Client(auth=auth) as client:
145
response = client.get('https://example.com/protected')
146
print(response.status_code)
147
```
148
149
### Digest Authentication
150
151
```python
152
import httpx
153
154
# Digest auth automatically handles the challenge-response flow
155
auth = httpx.DigestAuth('username', 'password')
156
response = httpx.get('https://httpbin.org/digest-auth/auth/username/password', auth=auth)
157
158
print(response.status_code) # 200 after successful authentication
159
```
160
161
### NetRC Authentication
162
163
```python
164
import httpx
165
166
# Uses credentials from ~/.netrc file
167
# Format: machine example.com login username password secret
168
auth = httpx.NetRCAuth()
169
response = httpx.get('https://example.com/protected', auth=auth)
170
171
# Custom .netrc file location
172
auth = httpx.NetRCAuth(file='/path/to/custom/.netrc')
173
response = httpx.get('https://example.com/protected', auth=auth)
174
```
175
176
### Client with Default Authentication
177
178
```python
179
import httpx
180
181
# All requests from this client will use authentication
182
auth = httpx.BasicAuth('api_key', '')
183
with httpx.Client(auth=auth, base_url='https://api.example.com') as client:
184
users = client.get('/users').json()
185
user = client.get('/users/123').json()
186
187
# Override auth for specific request
188
public_data = client.get('/public', auth=None).json()
189
```
190
191
### Async Authentication
192
193
```python
194
import httpx
195
import asyncio
196
197
async def main():
198
auth = httpx.BasicAuth('username', 'password')
199
200
async with httpx.AsyncClient(auth=auth) as client:
201
response = await client.get('https://example.com/protected')
202
print(response.json())
203
204
asyncio.run(main())
205
```
206
207
### Custom Authentication
208
209
```python
210
import httpx
211
212
class BearerAuth(httpx.Auth):
213
"""Custom Bearer token authentication."""
214
215
def __init__(self, token):
216
self.token = token
217
218
def auth_flow(self, request):
219
# Add Authorization header
220
request.headers['Authorization'] = f'Bearer {self.token}'
221
yield request
222
223
# Usage
224
auth = BearerAuth('your-token-here')
225
response = httpx.get('https://api.example.com/data', auth=auth)
226
```
227
228
### API Key Authentication
229
230
```python
231
import httpx
232
233
class APIKeyAuth(httpx.Auth):
234
"""Custom API key authentication via header."""
235
236
def __init__(self, api_key, header_name='X-API-Key'):
237
self.api_key = api_key
238
self.header_name = header_name
239
240
def auth_flow(self, request):
241
request.headers[self.header_name] = self.api_key
242
yield request
243
244
# Usage
245
auth = APIKeyAuth('your-api-key', 'X-API-Key')
246
with httpx.Client(auth=auth) as client:
247
response = client.get('https://api.example.com/data')
248
```
249
250
### OAuth 2.0 Bearer Token
251
252
```python
253
import httpx
254
255
class OAuth2Auth(httpx.Auth):
256
"""OAuth 2.0 Bearer token authentication."""
257
258
def __init__(self, access_token):
259
self.access_token = access_token
260
261
def auth_flow(self, request):
262
request.headers['Authorization'] = f'Bearer {self.access_token}'
263
yield request
264
265
# Usage
266
auth = OAuth2Auth('your-access-token')
267
response = httpx.get('https://api.example.com/user', auth=auth)
268
```
269
270
### Authentication with Retry Logic
271
272
```python
273
import httpx
274
import time
275
276
class TokenAuth(httpx.Auth):
277
"""Token authentication with automatic refresh."""
278
279
def __init__(self, get_token_func):
280
self.get_token_func = get_token_func
281
self.token = None
282
self.token_expires = 0
283
284
def auth_flow(self, request):
285
# Refresh token if expired
286
if time.time() >= self.token_expires:
287
self.token, expires_in = self.get_token_func()
288
self.token_expires = time.time() + expires_in - 60 # Refresh 60s early
289
290
request.headers['Authorization'] = f'Bearer {self.token}'
291
response = yield request
292
293
# If unauthorized, try refreshing token once
294
if response.status_code == 401:
295
self.token, expires_in = self.get_token_func()
296
self.token_expires = time.time() + expires_in - 60
297
request.headers['Authorization'] = f'Bearer {self.token}'
298
yield request
299
300
def get_access_token():
301
"""Function to obtain access token."""
302
# Implement token acquisition logic
303
return 'new-token', 3600 # token, expires_in_seconds
304
305
auth = TokenAuth(get_access_token)
306
with httpx.Client(auth=auth) as client:
307
response = client.get('https://api.example.com/data')
308
```
309
310
### Multiple Authentication Schemes
311
312
```python
313
import httpx
314
315
# Different authentication for different endpoints
316
basic_auth = httpx.BasicAuth('user', 'pass')
317
digest_auth = httpx.DigestAuth('user', 'pass')
318
319
with httpx.Client() as client:
320
# Basic auth for one endpoint
321
response1 = client.get('https://example.com/basic', auth=basic_auth)
322
323
# Digest auth for another endpoint
324
response2 = client.get('https://example.com/digest', auth=digest_auth)
325
326
# No auth for public endpoint
327
response3 = client.get('https://example.com/public')
328
```
329
330
### Error Handling
331
332
```python
333
import httpx
334
335
auth = httpx.BasicAuth('wrong-user', 'wrong-pass')
336
337
try:
338
response = httpx.get('https://httpbin.org/basic-auth/user/pass', auth=auth)
339
response.raise_for_status()
340
except httpx.HTTPStatusError as exc:
341
if exc.response.status_code == 401:
342
print("Authentication failed")
343
else:
344
print(f"HTTP error: {exc.response.status_code}")
345
except httpx.RequestError as exc:
346
print(f"Request error: {exc}")
347
```