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

multi-auth.mddocs/

0

# Multi-Authentication

1

2

Combines multiple authentication methods into a single handler, automatically selecting the appropriate authentication method based on request headers. MultiAuth enables flexible endpoint protection with fallback authentication schemes.

3

4

## Capabilities

5

6

### MultiAuth Class

7

8

Creates a multi-authentication handler that combines different authentication methods.

9

10

```python { .api }

11

class MultiAuth:

12

def __init__(self, main_auth, *args):

13

"""

14

Initialize multi-authentication handler.

15

16

Parameters:

17

- main_auth: Primary authentication method (used as fallback)

18

- *args: Additional authentication methods to support

19

20

Usage:

21

multi_auth = MultiAuth(basic_auth, token_auth, digest_auth)

22

"""

23

```

24

25

### Route Protection

26

27

Protect Flask routes with automatic authentication method selection.

28

29

```python { .api }

30

def login_required(self, f=None, role=None, optional=None):

31

"""

32

Decorator to require authentication using any compatible method.

33

34

Parameters:

35

- f (function, optional): Flask route function to protect

36

- role (str|list, optional): Required user role(s)

37

- optional (bool, optional): Make authentication optional

38

39

Returns:

40

Decorated function or decorator

41

42

Usage:

43

@multi_auth.login_required

44

def flexible_endpoint():

45

return f"Hello {multi_auth.current_user()}"

46

47

@multi_auth.login_required(role='admin')

48

def admin_endpoint():

49

return "Admin access via any auth method"

50

"""

51

```

52

53

### User Information

54

55

Access current authenticated user information within protected routes.

56

57

```python { .api }

58

def current_user(self):

59

"""

60

Get current authenticated user from whichever auth method was used.

61

62

Returns:

63

User object from the authentication method that handled the request

64

"""

65

```

66

67

## Usage Examples

68

69

### Basic + Token Authentication

70

71

```python

72

from flask import Flask

73

from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth, MultiAuth

74

from werkzeug.security import generate_password_hash, check_password_hash

75

76

app = Flask(__name__)

77

78

# Set up Basic authentication

79

basic_auth = HTTPBasicAuth()

80

users = {

81

"john": generate_password_hash("hello"),

82

"susan": generate_password_hash("bye")

83

}

84

85

@basic_auth.verify_password

86

def verify_password(username, password):

87

if username in users and check_password_hash(users.get(username), password):

88

return username

89

90

# Set up Token authentication

91

token_auth = HTTPTokenAuth('Bearer')

92

tokens = {

93

"secret-token-1": "john",

94

"secret-token-2": "susan"

95

}

96

97

@token_auth.verify_token

98

def verify_token(token):

99

return tokens.get(token)

100

101

# Combine authentication methods

102

multi_auth = MultiAuth(basic_auth, token_auth)

103

104

@app.route('/api/data')

105

@multi_auth.login_required

106

def get_data():

107

return {

108

"user": multi_auth.current_user(),

109

"data": "Available via Basic auth or Bearer token"

110

}

111

112

# Usage examples:

113

# curl -u john:hello http://localhost:5000/api/data

114

# curl -H "Authorization: Bearer secret-token-1" http://localhost:5000/api/data

115

```

116

117

### Three-Way Authentication

118

119

```python

120

from flask import Flask

121

from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth, HTTPDigestAuth, MultiAuth

122

123

app = Flask(__name__)

124

app.config['SECRET_KEY'] = 'secret key'

125

126

# Set up Basic authentication

127

basic_auth = HTTPBasicAuth()

128

129

@basic_auth.verify_password

130

def verify_basic_password(username, password):

131

users = {"john": "hello", "susan": "bye"}

132

if username in users and users[username] == password:

133

return username

134

135

# Set up Digest authentication

136

digest_auth = HTTPDigestAuth()

137

138

@digest_auth.get_password

139

def get_digest_password(username):

140

users = {"john": "hello", "susan": "bye"}

141

return users.get(username)

142

143

# Set up Token authentication

144

token_auth = HTTPTokenAuth('Bearer')

145

146

@token_auth.verify_token

147

def verify_token(token):

148

tokens = {"token123": "john", "token456": "susan"}

149

return tokens.get(token)

150

151

# Combine all three methods

152

multi_auth = MultiAuth(basic_auth, digest_auth, token_auth)

153

154

@app.route('/api/flexible')

155

@multi_auth.login_required

156

def flexible_endpoint():

157

return {

158

"message": f"Hello {multi_auth.current_user()}",

159

"auth_method": "Any of: Basic, Digest, or Bearer token"

160

}

161

```

162

163

### Role-Based Multi-Auth

164

165

```python

166

from flask import Flask

167

from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth, MultiAuth

168

169

app = Flask(__name__)

170

171

# Set up authentication methods

172

basic_auth = HTTPBasicAuth()

173

token_auth = HTTPTokenAuth('Bearer')

174

175

# User database with roles

176

users = {

177

"john": {"password": "hello", "roles": ["user"]},

178

"susan": {"password": "bye", "roles": ["user", "admin"]},

179

"admin": {"password": "secret", "roles": ["admin"]}

180

}

181

182

tokens = {

183

"user-token": {"user": "john", "roles": ["user"]},

184

"admin-token": {"user": "susan", "roles": ["user", "admin"]}

185

}

186

187

@basic_auth.verify_password

188

def verify_password(username, password):

189

if username in users and users[username]["password"] == password:

190

return {"username": username, "roles": users[username]["roles"]}

191

192

@basic_auth.get_user_roles

193

def get_basic_user_roles(user):

194

return user["roles"]

195

196

@token_auth.verify_token

197

def verify_token(token):

198

if token in tokens:

199

return tokens[token]

200

201

@token_auth.get_user_roles

202

def get_token_user_roles(user):

203

return user["roles"]

204

205

# Combine with role support

206

multi_auth = MultiAuth(basic_auth, token_auth)

207

208

@app.route('/api/user')

209

@multi_auth.login_required(role='user')

210

def user_endpoint():

211

return {"message": f"User access: {multi_auth.current_user()}"}

212

213

@app.route('/api/admin')

214

@multi_auth.login_required(role='admin')

215

def admin_endpoint():

216

return {"message": f"Admin access: {multi_auth.current_user()}"}

217

```

218

219

### Custom Authentication Priority

220

221

```python

222

from flask import Flask

223

from flask_httpauth import HTTPBasicAuth, HTTPTokenAuth, MultiAuth

224

225

app = Flask(__name__)

226

227

# High-priority authentication (checked first)

228

api_key_auth = HTTPTokenAuth('ApiKey', header='X-API-Key')

229

230

@api_key_auth.verify_token

231

def verify_api_key(key):

232

if key == "premium-api-key":

233

return {"user": "premium_user", "tier": "premium"}

234

235

# Fallback authentication

236

basic_auth = HTTPBasicAuth()

237

238

@basic_auth.verify_password

239

def verify_password(username, password):

240

if username == "regular" and password == "user":

241

return {"user": "regular_user", "tier": "basic"}

242

243

# API key auth has priority over basic auth

244

multi_auth = MultiAuth(api_key_auth, basic_auth)

245

246

@app.route('/api/service')

247

@multi_auth.login_required

248

def service_endpoint():

249

user = multi_auth.current_user()

250

return {

251

"user": user["user"],

252

"tier": user["tier"],

253

"message": "Service accessed with priority auth selection"

254

}

255

256

# Usage:

257

# curl -H "X-API-Key: premium-api-key" http://localhost:5000/api/service (premium)

258

# curl -u regular:user http://localhost:5000/api/service (basic)

259

```

260

261

## Authentication Method Selection

262

263

MultiAuth automatically selects the appropriate authentication method based on request headers:

264

265

1. **Header Inspection**: Examines incoming request headers

266

2. **Compatibility Check**: Tests each auth method's `is_compatible_auth()` method

267

3. **First Match**: Uses the first compatible authentication method found

268

4. **Fallback**: Uses main authentication method if no others match

269

270

The selection order follows the constructor parameter order: `MultiAuth(first_priority, second_priority, ...)`.

271

272

## Error Handling

273

274

MultiAuth delegates error handling to the selected authentication method:

275

276

- **401 Unauthorized**: No compatible authentication method found valid credentials

277

- **403 Forbidden**: Authentication succeeded but role authorization failed

278

- **Method-Specific Errors**: Each auth method handles its own error responses

279

- **Automatic Header**: WWW-Authenticate header from the selected auth method

280

281

The error response format depends on which authentication method processed the request.