0
# Authentication System
1
2
Authentication framework for securing REST API endpoints. Provides pluggable authentication handlers with support for HTTP Basic authentication and custom authentication callbacks.
3
4
## Capabilities
5
6
### Base Authentication Classes
7
8
Core authentication interfaces and data structures.
9
10
```python { .api }
11
class HTTPAuth:
12
"""
13
A base class from which all authentication classes should inherit.
14
"""
15
16
def get_authorization(self):
17
"""
18
Get the authorization header.
19
20
Returns:
21
Authorization: The authentication data or None if not present or invalid
22
23
Raises:
24
NotImplemented: Must be implemented by subclasses
25
"""
26
27
def get_authenticate_header(self):
28
"""
29
Return the value of WWW-Authenticate header in a 401 Unauthenticated response.
30
31
Returns:
32
str: WWW-Authenticate header value
33
"""
34
35
class Authorization(dict):
36
"""
37
A class to hold the authorization data.
38
39
Args:
40
auth_type (str): The authorization type (e.g., "basic", "bearer")
41
**kwargs: Additional authorization data
42
43
Attributes:
44
auth_type (str): The authorization type
45
"""
46
47
def __init__(self, auth_type, **kwargs):
48
"""
49
Initialize Authorization object.
50
51
Args:
52
auth_type (str): Authorization type ("basic", "bearer", etc.)
53
**kwargs: Authorization-specific data
54
"""
55
```
56
57
### HTTP Basic Authentication
58
59
Implementation of HTTP Basic authentication for API endpoints.
60
61
```python { .api }
62
class HTTPBasicAuth(HTTPAuth):
63
"""
64
HTTP Basic authentication implementation.
65
66
Attributes:
67
www_authenticate_realm (str): Authentication realm for WWW-Authenticate header
68
"""
69
70
www_authenticate_realm: str = "Authentication Required"
71
72
def get_authorization(self):
73
"""
74
Get the username and password for Basic authentication header.
75
76
Returns:
77
Authorization: Authorization object with username and password, or None
78
79
Authorization object contains:
80
auth_type (str): "basic"
81
username (str): Decoded username
82
password (str): Decoded password
83
"""
84
85
def get_authenticate_header(self):
86
"""
87
Return the value of WWW-Authenticate header for Basic auth.
88
89
Returns:
90
str: Basic realm="[realm]" header value
91
"""
92
```
93
94
### Authorization Header Parsing
95
96
Utility function for parsing HTTP Authorization headers.
97
98
```python { .api }
99
def get_authorization_header():
100
"""
101
Return request's 'Authorization:' header as a two-tuple of (type, info).
102
103
Returns:
104
tuple: (auth_type, auth_info) or None if header missing or invalid
105
106
Examples:
107
("basic", b"dXNlcjpwYXNz") # For "Basic dXNlcjpwYXNz"
108
("bearer", b"token123") # For "Bearer token123"
109
"""
110
```
111
112
## Usage Examples
113
114
### Basic Authentication Setup
115
116
```python
117
from flask import Flask
118
from flask_apscheduler import APScheduler
119
from flask_apscheduler.auth import HTTPBasicAuth
120
121
class Config:
122
SCHEDULER_API_ENABLED = True
123
SCHEDULER_AUTH = HTTPBasicAuth()
124
125
app = Flask(__name__)
126
app.config.from_object(Config())
127
128
scheduler = APScheduler()
129
scheduler.init_app(app)
130
131
# Define authentication callback
132
@scheduler.authenticate
133
def authenticate(auth):
134
"""
135
Authenticate users for API access.
136
137
Args:
138
auth (Authorization): Authorization object with username/password
139
140
Returns:
141
bool: True if authentication successful, False otherwise
142
"""
143
return auth["username"] == "admin" and auth["password"] == "secret"
144
145
scheduler.start()
146
```
147
148
### Custom Authentication Realm
149
150
```python
151
from flask_apscheduler.auth import HTTPBasicAuth
152
153
# Create auth handler with custom realm
154
auth_handler = HTTPBasicAuth()
155
auth_handler.www_authenticate_realm = "Scheduler API"
156
157
class Config:
158
SCHEDULER_API_ENABLED = True
159
SCHEDULER_AUTH = auth_handler
160
161
app.config.from_object(Config())
162
```
163
164
### Direct Authentication Assignment
165
166
```python
167
from flask_apscheduler import APScheduler
168
from flask_apscheduler.auth import HTTPBasicAuth
169
170
scheduler = APScheduler()
171
scheduler.auth = HTTPBasicAuth() # Set directly on scheduler instance
172
173
@scheduler.authenticate
174
def authenticate(auth):
175
# Check against database, LDAP, etc.
176
user = get_user_from_database(auth["username"])
177
return user and user.check_password(auth["password"])
178
```
179
180
### Advanced Authentication Callback
181
182
```python
183
import hashlib
184
import hmac
185
186
@scheduler.authenticate
187
def authenticate(auth):
188
"""
189
Advanced authentication with multiple user support and secure password checking.
190
"""
191
# Multiple valid users
192
users = {
193
"admin": "hashed_admin_password",
194
"operator": "hashed_operator_password",
195
"readonly": "hashed_readonly_password"
196
}
197
198
username = auth.get("username")
199
password = auth.get("password")
200
201
if not username or not password:
202
return False
203
204
stored_hash = users.get(username)
205
if not stored_hash:
206
return False
207
208
# Secure password comparison
209
expected_hash = hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), b'salt', 100000)
210
return hmac.compare_digest(stored_hash.encode(), expected_hash.hex().encode())
211
```
212
213
### Custom Authentication Class
214
215
```python
216
from flask import request
217
from flask_apscheduler.auth import HTTPAuth, Authorization
218
219
class APIKeyAuth(HTTPAuth):
220
"""Custom API key authentication."""
221
222
def __init__(self, valid_keys):
223
self.valid_keys = valid_keys
224
225
def get_authorization(self):
226
"""Extract API key from X-API-Key header."""
227
api_key = request.headers.get('X-API-Key')
228
if not api_key:
229
return None
230
231
if api_key in self.valid_keys:
232
return Authorization("apikey", key=api_key)
233
return None
234
235
def get_authenticate_header(self):
236
"""Return custom auth challenge."""
237
return 'API-Key realm="Scheduler API"'
238
239
# Use custom authentication
240
api_keys = ["key1", "key2", "key3"]
241
scheduler.auth = APIKeyAuth(api_keys)
242
243
@scheduler.authenticate
244
def authenticate(auth):
245
# API key already validated in get_authorization
246
return auth["key"] in api_keys
247
```
248
249
### No Authentication (Development Only)
250
251
```python
252
class Config:
253
SCHEDULER_API_ENABLED = True
254
# SCHEDULER_AUTH not set - no authentication required
255
256
# Or explicitly disable
257
scheduler.auth = None
258
```
259
260
## Making Authenticated Requests
261
262
### Basic Authentication Requests
263
264
```bash
265
# Using curl with Basic auth
266
curl -u admin:secret http://localhost:5000/scheduler
267
268
# Using Authorization header directly
269
curl -H "Authorization: Basic YWRtaW46c2VjcmV0" \
270
http://localhost:5000/scheduler/jobs
271
272
# Add job with authentication
273
curl -u admin:secret \
274
-X POST http://localhost:5000/scheduler/jobs \
275
-H "Content-Type: application/json" \
276
-d '{"id": "test", "func": "tasks:test_task", "trigger": "interval", "seconds": 30}'
277
```
278
279
### Python Requests Example
280
281
```python
282
import requests
283
from requests.auth import HTTPBasicAuth
284
285
# Get scheduler info
286
response = requests.get(
287
'http://localhost:5000/scheduler',
288
auth=HTTPBasicAuth('admin', 'secret')
289
)
290
291
# Add job
292
job_data = {
293
"id": "python_job",
294
"func": "tasks:my_task",
295
"trigger": "interval",
296
"seconds": 60
297
}
298
299
response = requests.post(
300
'http://localhost:5000/scheduler/jobs',
301
json=job_data,
302
auth=HTTPBasicAuth('admin', 'secret')
303
)
304
```
305
306
## Authentication Flow
307
308
1. **API Request**: Client makes request to protected endpoint
309
2. **Header Check**: Flask-APScheduler checks for Authorization header
310
3. **Parse Credentials**: Authentication handler parses credentials from header
311
4. **Validation**: Custom authenticate callback validates credentials
312
5. **Response**:
313
- Success: Process request normally
314
- Failure: Return 401 with WWW-Authenticate header
315
316
## Configuration Options
317
318
```python { .api }
319
# Authentication configuration
320
SCHEDULER_AUTH: HTTPAuth = None # Authentication handler instance
321
322
# Built-in options
323
HTTPBasicAuth.www_authenticate_realm: str = "Authentication Required"
324
```
325
326
## Error Responses
327
328
### Unauthorized Access
329
330
```http
331
HTTP/1.1 401 Unauthorized
332
WWW-Authenticate: Basic realm="Authentication Required"
333
Content-Type: text/plain
334
335
Access Denied
336
```
337
338
### Missing Credentials
339
340
Same as unauthorized - returns 401 with WWW-Authenticate header to prompt for credentials.
341
342
### Invalid Credentials
343
344
Same response as missing credentials to avoid revealing valid usernames.