or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

basic-auth.mddigest-auth.mdindex.mdmulti-auth.mdroles.mdtoken-auth.md

roles.mddocs/

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.