0
# Role-Based Authorization
1
2
Role-based access control system that works across all Flask-HTTPAuth authentication methods. Supports simple roles, multiple roles per user, and complex role hierarchies with flexible authorization callbacks.
3
4
## Capabilities
5
6
### User Role Configuration
7
8
Register callback functions to define user roles for authorization.
9
10
```python { .api }
11
def get_user_roles(self, f):
12
"""
13
Decorator to register user role retrieval callback.
14
Available on all authentication classes (HTTPAuth base class).
15
16
Parameters:
17
- f (function): Callback function(user) -> roles
18
19
Returns:
20
The decorated function
21
22
Usage:
23
@auth.get_user_roles
24
def get_user_roles(user):
25
# Return user roles as string, list, or set
26
return user_roles
27
"""
28
```
29
30
### Role-Based Route Protection
31
32
Protect Flask routes with role requirements using the login_required decorator.
33
34
```python { .api }
35
def login_required(self, f=None, role=None, optional=None):
36
"""
37
Decorator with role-based authorization support.
38
Available on all authentication classes.
39
40
Parameters:
41
- f (function, optional): Flask route function to protect
42
- role (str|list|tuple, optional): Required role(s)
43
- optional (bool, optional): Make authentication optional
44
45
Returns:
46
Decorated function or decorator
47
48
Role Matching:
49
- Single role: role='admin'
50
- Multiple roles (OR): role=['admin', 'moderator']
51
- Multiple roles (AND): role=[['read', 'write']]
52
53
Usage:
54
@auth.login_required(role='admin')
55
def admin_only():
56
return "Admin access"
57
58
@auth.login_required(role=['admin', 'moderator'])
59
def staff_access():
60
return "Admin or moderator access"
61
62
@auth.login_required(role=[['read', 'write']])
63
def full_permissions():
64
return "Must have both read AND write roles"
65
"""
66
```
67
68
### Role Authorization Logic
69
70
Internal authorization checking with support for complex role hierarchies.
71
72
```python { .api }
73
def authorize(self, role, user, auth):
74
"""
75
Check if user is authorized for the required role(s).
76
Internal method called by login_required decorator.
77
78
Parameters:
79
- role (str|list|tuple|None): Required role(s)
80
- user: User object returned by authentication callback
81
- auth: Authentication object from request
82
83
Returns:
84
bool: True if authorized, False otherwise
85
86
Authorization Rules:
87
- None role: Always authorized (no role required)
88
- Single role: User must have exact role
89
- List roles: User must have at least one role (OR logic)
90
- Nested list: User must have all roles in inner list (AND logic)
91
"""
92
```
93
94
## Usage Examples
95
96
### Simple Role System
97
98
```python
99
from flask import Flask
100
from flask_httpauth import HTTPBasicAuth
101
102
app = Flask(__name__)
103
auth = HTTPBasicAuth()
104
105
# User database with roles
106
users = {
107
"john": {"password": "hello", "role": "user"},
108
"susan": {"password": "bye", "role": "admin"},
109
"bob": {"password": "secret", "role": "moderator"}
110
}
111
112
@auth.verify_password
113
def verify_password(username, password):
114
if username in users and users[username]["password"] == password:
115
return users[username]
116
117
@auth.get_user_roles
118
def get_user_roles(user):
119
return user["role"]
120
121
@app.route('/public')
122
def public():
123
return "Public access"
124
125
@app.route('/user')
126
@auth.login_required(role='user')
127
def user_area():
128
return f"User area: {auth.current_user()['role']}"
129
130
@app.route('/admin')
131
@auth.login_required(role='admin')
132
def admin_area():
133
return f"Admin area: {auth.current_user()['role']}"
134
```
135
136
### Multiple Roles Per User
137
138
```python
139
from flask import Flask
140
from flask_httpauth import HTTPBasicAuth
141
142
app = Flask(__name__)
143
auth = HTTPBasicAuth()
144
145
# Users with multiple roles
146
users = {
147
"john": {"password": "hello", "roles": ["user"]},
148
"susan": {"password": "bye", "roles": ["user", "admin"]},
149
"bob": {"password": "secret", "roles": ["user", "moderator"]},
150
"alice": {"password": "key", "roles": ["admin", "moderator"]}
151
}
152
153
@auth.verify_password
154
def verify_password(username, password):
155
if username in users and users[username]["password"] == password:
156
return users[username]
157
158
@auth.get_user_roles
159
def get_user_roles(user):
160
return user["roles"]
161
162
@app.route('/user')
163
@auth.login_required(role='user')
164
def user_area():
165
return "All authenticated users"
166
167
@app.route('/staff')
168
@auth.login_required(role=['admin', 'moderator'])
169
def staff_area():
170
return "Admin OR moderator access"
171
172
@app.route('/admin')
173
@auth.login_required(role='admin')
174
def admin_area():
175
return "Admin only"
176
```
177
178
### Complex Role Hierarchies
179
180
```python
181
from flask import Flask
182
from flask_httpauth import HTTPBasicAuth
183
184
app = Flask(__name__)
185
auth = HTTPBasicAuth()
186
187
# Complex role system with permissions
188
users = {
189
"john": {
190
"password": "hello",
191
"roles": ["read", "user"]
192
},
193
"susan": {
194
"password": "bye",
195
"roles": ["read", "write", "admin", "user"]
196
},
197
"bob": {
198
"password": "secret",
199
"roles": ["read", "write", "user"]
200
}
201
}
202
203
@auth.verify_password
204
def verify_password(username, password):
205
if username in users and users[username]["password"] == password:
206
return users[username]
207
208
@auth.get_user_roles
209
def get_user_roles(user):
210
return user["roles"]
211
212
@app.route('/read')
213
@auth.login_required(role='read')
214
def read_data():
215
return "Read access granted"
216
217
@app.route('/write')
218
@auth.login_required(role='write')
219
def write_data():
220
return "Write access granted"
221
222
@app.route('/edit')
223
@auth.login_required(role=[['read', 'write']])
224
def edit_data():
225
return "Edit requires BOTH read AND write permissions"
226
227
@app.route('/admin')
228
@auth.login_required(role='admin')
229
def admin_panel():
230
return "Admin panel access"
231
232
@app.route('/superuser')
233
@auth.login_required(role=[['admin', 'write']])
234
def superuser_area():
235
return "Requires BOTH admin AND write permissions"
236
```
237
238
### Database-Driven Roles
239
240
```python
241
from flask import Flask
242
from flask_httpauth import HTTPBasicAuth
243
244
app = Flask(__name__)
245
auth = HTTPBasicAuth()
246
247
# Simulate database lookup
248
class UserRoleManager:
249
def __init__(self):
250
# In real apps, this would be a database
251
self.users = {
252
"john": {"password": "hello", "id": 1},
253
"susan": {"password": "bye", "id": 2}
254
}
255
256
self.user_roles = {
257
1: ["user", "customer"],
258
2: ["user", "admin", "customer", "staff"]
259
}
260
261
def get_user(self, username, password):
262
user = self.users.get(username)
263
if user and user["password"] == password:
264
return user
265
return None
266
267
def get_roles(self, user_id):
268
return self.user_roles.get(user_id, [])
269
270
role_manager = UserRoleManager()
271
272
@auth.verify_password
273
def verify_password(username, password):
274
return role_manager.get_user(username, password)
275
276
@auth.get_user_roles
277
def get_user_roles(user):
278
return role_manager.get_roles(user["id"])
279
280
@app.route('/customer')
281
@auth.login_required(role='customer')
282
def customer_area():
283
return "Customer area"
284
285
@app.route('/staff')
286
@auth.login_required(role='staff')
287
def staff_area():
288
return "Staff area"
289
```
290
291
### Token Authentication with Roles
292
293
```python
294
from flask import Flask
295
from flask_httpauth import HTTPTokenAuth
296
import jwt
297
298
app = Flask(__name__)
299
app.config['SECRET_KEY'] = 'secret'
300
auth = HTTPTokenAuth('Bearer')
301
302
@auth.verify_token
303
def verify_token(token):
304
try:
305
# Decode JWT token with role information
306
data = jwt.decode(token, app.config['SECRET_KEY'], algorithms=['HS256'])
307
return {
308
"username": data["username"],
309
"roles": data.get("roles", [])
310
}
311
except jwt.InvalidTokenError:
312
return None
313
314
@auth.get_user_roles
315
def get_user_roles(user):
316
return user["roles"]
317
318
@app.route('/api/user')
319
@auth.login_required(role='user')
320
def user_api():
321
return {"message": f"User API: {auth.current_user()['username']}"}
322
323
@app.route('/api/admin')
324
@auth.login_required(role='admin')
325
def admin_api():
326
return {"message": f"Admin API: {auth.current_user()['username']}"}
327
328
# Token generation example
329
def generate_token(username, roles):
330
payload = {
331
"username": username,
332
"roles": roles,
333
"exp": datetime.utcnow() + timedelta(hours=1)
334
}
335
return jwt.encode(payload, app.config['SECRET_KEY'], algorithm='HS256')
336
```
337
338
## Role Matching Logic
339
340
Flask-HTTPAuth supports flexible role matching:
341
342
### Single Role
343
```python
344
@auth.login_required(role='admin')
345
# User must have exactly 'admin' role
346
```
347
348
### Multiple Roles (OR Logic)
349
```python
350
@auth.login_required(role=['admin', 'moderator'])
351
# User must have 'admin' OR 'moderator' role
352
```
353
354
### Multiple Roles (AND Logic)
355
```python
356
@auth.login_required(role=[['read', 'write']])
357
# User must have BOTH 'read' AND 'write' roles
358
```
359
360
### Complex Combinations
361
```python
362
@auth.login_required(role=[['admin', 'write'], 'superuser'])
363
# User must have (admin AND write) OR superuser
364
```
365
366
## Error Handling
367
368
Role-based authorization generates appropriate HTTP status codes:
369
370
- **401 Unauthorized**: Authentication failed or missing
371
- **403 Forbidden**: Authentication succeeded but insufficient role permissions
372
- **Automatic Role Check**: Performed after successful authentication
373
- **Custom Error Handlers**: Can be implemented using the `error_handler` decorator
374
375
The role authorization system integrates seamlessly with all Flask-HTTPAuth authentication methods and provides detailed error information for debugging role-based access issues.