0
# Authentication
1
2
Modular authentication system supporting HTTP Basic authentication, API key authentication (query parameter or header), and extensible custom authentication schemes. Authentication is applied per-host and integrates seamlessly with both synchronous and asynchronous HTTP clients.
3
4
## Capabilities
5
6
### Authenticator (Base Class)
7
8
Abstract base class for all authentication implementations. Provides host matching and request modification interface.
9
10
```python { .api }
11
class Authenticator:
12
def __init__(self, host: str): ...
13
def matches(self, url: str) -> bool: ...
14
def apply(self, request) -> requests.Request: ...
15
def __repr__(self) -> str: ...
16
```
17
18
**Parameters:**
19
- `host` (str): Hostname (including port if needed) that this authenticator applies to
20
- `url` (str): URL to check for host matching
21
- `request`: requests.Request object to modify with authentication
22
23
**Returns:**
24
- `matches`: True if the authenticator should be applied to the given URL
25
- `apply`: Modified request object with authentication applied
26
27
### BasicAuthenticator
28
29
HTTP Basic authentication implementation. Adds Authorization header with base64-encoded credentials.
30
31
```python { .api }
32
class BasicAuthenticator(Authenticator):
33
def __init__(self, host: str, username: str, password: str): ...
34
def apply(self, request) -> requests.Request: ...
35
```
36
37
**Parameters:**
38
- `host` (str): Hostname for authentication
39
- `username` (str): Username for basic auth
40
- `password` (str): Password for basic auth
41
42
**Usage Example:**
43
44
```python
45
from bravado.requests_client import BasicAuthenticator, RequestsClient
46
from bravado.client import SwaggerClient
47
48
# Create authenticator
49
auth = BasicAuthenticator('api.example.com', 'myuser', 'mypassword')
50
51
# Apply to HTTP client
52
http_client = RequestsClient()
53
http_client.set_basic_auth('api.example.com', 'myuser', 'mypassword')
54
55
# Use with SwaggerClient
56
client = SwaggerClient.from_url('https://api.example.com/swagger.json',
57
http_client=http_client)
58
```
59
60
### ApiKeyAuthenticator
61
62
API key authentication implementation. Supports API keys in query parameters or headers.
63
64
```python { .api }
65
class ApiKeyAuthenticator(Authenticator):
66
def __init__(self, host: str, api_key: str, param_name: str = 'api_key', param_in: str = 'query'): ...
67
def apply(self, request) -> requests.Request: ...
68
```
69
70
**Parameters:**
71
- `host` (str): Hostname for authentication
72
- `api_key` (str): API key value
73
- `param_name` (str): Parameter name for the API key (default: 'api_key')
74
- `param_in` (str): Where to place the API key - 'query' or 'header' (default: 'query')
75
76
**Usage Examples:**
77
78
```python
79
from bravado.requests_client import ApiKeyAuthenticator, RequestsClient
80
from bravado.client import SwaggerClient
81
82
# API key in query parameter
83
http_client = RequestsClient()
84
http_client.set_api_key('api.example.com', 'your-api-key-here', param_name='apikey')
85
86
# API key in header
87
http_client = RequestsClient()
88
http_client.set_api_key('api.example.com', 'your-api-key-here',
89
param_name='X-API-Key', param_in='header')
90
91
# Use with SwaggerClient
92
client = SwaggerClient.from_url('https://api.example.com/swagger.json',
93
http_client=http_client)
94
```
95
96
## RequestsClient Authentication Methods
97
98
The RequestsClient provides convenience methods for setting up authentication:
99
100
```python { .api }
101
class RequestsClient:
102
def set_basic_auth(self, host: str, username: str, password: str): ...
103
def set_api_key(self, host: str, api_key: str, param_name: str = 'api_key', param_in: str = 'query'): ...
104
def apply_authentication(self, request): ...
105
```
106
107
**Parameters:**
108
- `host` (str): Hostname for authentication
109
- `username` (str): Username for basic auth
110
- `password` (str): Password for basic auth
111
- `api_key` (str): API key value
112
- `param_name` (str): Parameter name for API key
113
- `param_in` (str): Location for API key ('query' or 'header')
114
115
These methods create and register the appropriate authenticator instances internally.
116
117
## Multiple Authentication
118
119
You can configure multiple authenticators for different hosts:
120
121
```python
122
from bravado.requests_client import RequestsClient
123
124
http_client = RequestsClient()
125
126
# Different auth for different services
127
http_client.set_basic_auth('api.service1.com', 'user1', 'pass1')
128
http_client.set_api_key('api.service2.com', 'key123', param_name='token', param_in='header')
129
130
# Authenticators are automatically selected based on request URL
131
```
132
133
## Custom Authenticators
134
135
Create custom authentication schemes by extending the Authenticator base class:
136
137
```python
138
from bravado.requests_client import Authenticator
139
import hmac
140
import hashlib
141
import time
142
143
class HMACAuthenticator(Authenticator):
144
def __init__(self, host, key_id, secret_key):
145
super().__init__(host)
146
self.key_id = key_id
147
self.secret_key = secret_key
148
149
def apply(self, request):
150
timestamp = str(int(time.time()))
151
152
# Create signature
153
message = f"{request.method}{request.url}{timestamp}"
154
signature = hmac.new(
155
self.secret_key.encode(),
156
message.encode(),
157
hashlib.sha256
158
).hexdigest()
159
160
# Add authentication headers
161
request.headers['X-Auth-Key'] = self.key_id
162
request.headers['X-Auth-Timestamp'] = timestamp
163
request.headers['X-Auth-Signature'] = signature
164
165
return request
166
167
# Use custom authenticator
168
auth = HMACAuthenticator('api.example.com', 'key123', 'secret456')
169
http_client = RequestsClient()
170
# Note: Custom authenticators need to be manually added to the client's authenticators list
171
```
172
173
## Authentication Debugging
174
175
When authentication fails, check the following:
176
177
1. **Host Matching**: Ensure the authenticator host matches the request URL exactly
178
2. **Parameter Names**: Verify API key parameter names match the API specification
179
4. **URL Structure**: Check if the API expects authentication on all endpoints or specific paths
180
181
```python
182
# Enable debug logging to see authentication details
183
import logging
184
logging.basicConfig(level=logging.DEBUG)
185
186
# Check if authenticator matches
187
auth = BasicAuthenticator('api.example.com', 'user', 'pass')
188
print(auth.matches('https://api.example.com/pets')) # Should be True
189
print(auth.matches('https://other.example.com/pets')) # Should be False
190
```
191
192
## Security Considerations
193
194
- **HTTPS**: Always use HTTPS when transmitting credentials
195
- **Key Storage**: Store API keys and passwords securely (environment variables, key management systems)
196
- **Key Rotation**: Implement proper key rotation practices
197
- **Scope Limitation**: Use API keys with minimal required permissions
198
199
```python
200
import os
201
from bravado.requests_client import RequestsClient
202
203
# Good: Load credentials from environment
204
http_client = RequestsClient()
205
http_client.set_api_key(
206
'api.example.com',
207
os.environ['API_KEY'], # Never hardcode keys
208
param_name='Authorization',
209
param_in='header'
210
)
211
```