0
# Authentication and Authorization
1
2
Pluggable authentication and authorization system with support for various credential types, checkers, and realms for securing network services. Twisted Cred provides a flexible framework for implementing authentication across different protocols.
3
4
## Capabilities
5
6
### Portal and Realm
7
8
Core authentication coordination and user domain management.
9
10
```python { .api }
11
class portal.Portal:
12
"""
13
Authentication coordinator that manages checkers and realms.
14
15
Attributes:
16
- realm: Authentication realm (IRealm)
17
- checkers: Dict of credential interfaces to checker lists
18
"""
19
realm = None
20
checkers = None
21
22
def __init__(self, realm, checkers=None):
23
"""
24
Args:
25
realm: Authentication realm (IRealm)
26
checkers: Sequence of credential checkers
27
"""
28
29
def registerChecker(self, checker, interface=None):
30
"""
31
Register a credentials checker.
32
33
Args:
34
checker: Credentials checker (ICredentialsChecker)
35
interface: Credential interface this checker handles
36
"""
37
38
def login(self, credentials, mind, *interfaces):
39
"""
40
Authenticate user and return avatar.
41
42
Args:
43
credentials: User credentials (ICredentials)
44
mind: User's perspective object
45
*interfaces: Requested avatar interfaces
46
47
Returns:
48
Deferred: Fires with (interface, avatar, logout) tuple
49
"""
50
51
class portal.IRealm:
52
"""
53
Interface for authentication realms.
54
55
Realms define the domain of authenticated users and create
56
avatars representing users in the system.
57
"""
58
def requestAvatar(avatarId, mind, *interfaces):
59
"""
60
Create avatar for authenticated user.
61
62
Args:
63
avatarId: Unique user identifier
64
mind: User's perspective object
65
*interfaces: Requested avatar interfaces
66
67
Returns:
68
tuple: (interface, avatar, logout_callable)
69
"""
70
```
71
72
**Portal Usage Example**:
73
74
```python
75
from twisted.cred import portal, checkers
76
from twisted.internet import defer
77
78
class SimpleRealm:
79
"""Simple realm that creates user avatars."""
80
81
def requestAvatar(self, avatarId, mind, *interfaces):
82
if IUser in interfaces:
83
avatar = User(avatarId)
84
logout = lambda: None # Cleanup function
85
return (IUser, avatar, logout)
86
raise NotImplementedError("Interface not supported")
87
88
# Create portal with realm and checker
89
realm = SimpleRealm()
90
checker = checkers.InMemoryUsernamePasswordDatabaseDontUse()
91
checker.addUser(b"alice", b"password123")
92
93
portal_obj = portal.Portal(realm, [checker])
94
95
# Login user
96
from twisted.cred.credentials import UsernamePassword
97
credentials = UsernamePassword(b"alice", b"password123")
98
99
d = portal_obj.login(credentials, None, IUser)
100
d.addCallback(lambda result: print(f"Logged in: {result[1]}"))
101
```
102
103
### Credentials
104
105
Different types of user credentials for authentication.
106
107
```python { .api }
108
class credentials.ICredentials:
109
"""
110
Base interface for user credentials.
111
"""
112
113
class credentials.IUsernamePassword:
114
"""
115
Interface for username/password credentials.
116
117
Attributes:
118
- username: Username (bytes)
119
- password: Password (bytes)
120
"""
121
username = None
122
password = None
123
124
class credentials.UsernamePassword:
125
"""
126
Username and password credentials.
127
"""
128
def __init__(self, username, password):
129
"""
130
Args:
131
username (bytes): Username
132
password (bytes): Password
133
"""
134
135
def checkPassword(self, password):
136
"""
137
Check if password matches.
138
139
Args:
140
password (bytes): Password to check
141
142
Returns:
143
bool: True if password matches
144
"""
145
146
class credentials.IUsernameHashedPassword:
147
"""
148
Interface for username with hashed password credentials.
149
150
Attributes:
151
- username: Username (bytes)
152
- hashed: Hashed password (bytes)
153
"""
154
username = None
155
hashed = None
156
157
class credentials.UsernameHashedPassword:
158
"""
159
Username and hashed password credentials.
160
"""
161
def __init__(self, username, hashed):
162
"""
163
Args:
164
username (bytes): Username
165
hashed (bytes): Hashed password
166
"""
167
168
def checkPassword(self, password):
169
"""
170
Check password against hash.
171
172
Args:
173
password (bytes): Plain password to check
174
175
Returns:
176
bool: True if password matches hash
177
"""
178
179
class credentials.IAnonymous:
180
"""
181
Interface for anonymous credentials.
182
"""
183
184
class credentials.Anonymous:
185
"""
186
Anonymous credentials for unauthenticated access.
187
"""
188
189
class credentials.ISSHPrivateKey:
190
"""
191
Interface for SSH private key credentials.
192
193
Attributes:
194
- username: Username (bytes)
195
- algName: Key algorithm name (bytes)
196
- keyData: Public key data (bytes)
197
- signature: Authentication signature (bytes)
198
"""
199
username = None
200
algName = None
201
keyData = None
202
signature = None
203
204
class credentials.SSHPrivateKey:
205
"""
206
SSH private key credentials.
207
"""
208
def __init__(self, username, algName, keyData, signature, sigData):
209
"""
210
Args:
211
username (bytes): Username
212
algName (bytes): Key algorithm
213
keyData (bytes): Public key data
214
signature (bytes): Signature
215
sigData (bytes): Signed data
216
"""
217
```
218
219
### Credential Checkers
220
221
Implementations for verifying different types of credentials.
222
223
```python { .api }
224
class checkers.ICredentialsChecker:
225
"""
226
Interface for credential verification.
227
228
Attributes:
229
- credentialInterfaces: Supported credential types
230
"""
231
credentialInterfaces = None
232
233
def requestAvatarId(credentials):
234
"""
235
Verify credentials and return avatar ID.
236
237
Args:
238
credentials: User credentials (ICredentials)
239
240
Returns:
241
Deferred: Fires with avatar ID on success
242
"""
243
244
class checkers.InMemoryUsernamePasswordDatabaseDontUse:
245
"""
246
In-memory username/password database.
247
248
WARNING: For testing only - stores passwords in plain text.
249
"""
250
def __init__(self):
251
"""Initialize empty user database."""
252
self.users = {}
253
254
def addUser(self, username, password):
255
"""
256
Add user to database.
257
258
Args:
259
username (bytes): Username
260
password (bytes): Password
261
"""
262
263
def requestAvatarId(self, credentials):
264
"""
265
Check username/password credentials.
266
267
Args:
268
credentials: Username/password credentials
269
270
Returns:
271
Deferred: Avatar ID on success
272
"""
273
274
class checkers.FilePasswordDB:
275
"""
276
File-based password database.
277
"""
278
def __init__(self, filename, delim=b':', usernameField=0, passwordField=1, caseSensitive=True, hash=None, cache=False):
279
"""
280
Args:
281
filename (str): Password file path
282
delim (bytes): Field delimiter
283
usernameField (int): Username field index
284
passwordField (int): Password field index
285
caseSensitive (bool): Case-sensitive usernames
286
hash: Password hash function
287
cache (bool): Cache file contents
288
"""
289
290
def requestAvatarId(self, credentials):
291
"""
292
Check credentials against file database.
293
294
Args:
295
credentials: Username/password credentials
296
297
Returns:
298
Deferred: Avatar ID on success
299
"""
300
301
class checkers.AllowAnonymousAccess:
302
"""
303
Checker that allows anonymous access.
304
"""
305
credentialInterfaces = (credentials.IAnonymous,)
306
307
def requestAvatarId(self, credentials):
308
"""
309
Allow anonymous access.
310
311
Args:
312
credentials: Anonymous credentials
313
314
Returns:
315
Deferred: Anonymous avatar ID
316
"""
317
318
class checkers.SSHPublicKeyDatabase:
319
"""
320
SSH public key database checker.
321
"""
322
def checkKey(self, credentials):
323
"""
324
Verify SSH public key credentials.
325
326
Args:
327
credentials: SSH key credentials
328
329
Returns:
330
Deferred: Avatar ID on success
331
"""
332
333
def requestAvatarId(self, credentials):
334
"""
335
Check SSH key credentials.
336
337
Args:
338
credentials: SSH private key credentials
339
340
Returns:
341
Deferred: Avatar ID on success
342
"""
343
```
344
345
**Checker Usage Example**:
346
347
```python
348
from twisted.cred import checkers, credentials
349
from twisted.internet import defer
350
351
# In-memory checker
352
memory_checker = checkers.InMemoryUsernamePasswordDatabaseDontUse()
353
memory_checker.addUser(b"admin", b"secret")
354
memory_checker.addUser(b"user", b"password")
355
356
# File-based checker
357
file_checker = checkers.FilePasswordDB("/etc/passwd", delim=b":")
358
359
# Anonymous access checker
360
anon_checker = checkers.AllowAnonymousAccess()
361
362
# Test authentication
363
creds = credentials.UsernamePassword(b"admin", b"secret")
364
d = memory_checker.requestAvatarId(creds)
365
d.addCallback(lambda avatar_id: print(f"Authenticated: {avatar_id}"))
366
d.addErrback(lambda failure: print(f"Auth failed: {failure.value}"))
367
```
368
369
### Authentication Errors
370
371
Exception types for authentication failures.
372
373
```python { .api }
374
class error.Unauthorized:
375
"""
376
Base class for authentication failures.
377
"""
378
379
class error.UnauthorizedLogin:
380
"""
381
Login attempt with invalid credentials.
382
"""
383
384
class error.UnhandledCredentials:
385
"""
386
No suitable checker found for credential type.
387
"""
388
389
class error.LoginFailed:
390
"""
391
Generic login failure.
392
"""
393
394
class error.LoginDenied:
395
"""
396
Login denied by policy.
397
"""
398
```
399
400
### String-based Credential Configuration
401
402
Utilities for configuring authentication from strings.
403
404
```python { .api }
405
def strcred.makeChecker(description):
406
"""
407
Create credential checker from string description.
408
409
Args:
410
description (str): Checker specification
411
412
Returns:
413
ICredentialsChecker: Configured checker
414
"""
415
416
# String checker formats:
417
# "memory:user1:pass1:user2:pass2" - In-memory database
418
# "file:/path/to/passwd" - File-based database
419
# "unix" - Unix system accounts
420
# "anonymous" - Allow anonymous access
421
```
422
423
**String Configuration Example**:
424
425
```python
426
from twisted.cred import strcred
427
428
# Create checkers from string descriptions
429
memory_checker = strcred.makeChecker("memory:alice:secret:bob:password")
430
file_checker = strcred.makeChecker("file:/etc/twisted-passwd")
431
anon_checker = strcred.makeChecker("anonymous")
432
433
# Use in portal
434
from twisted.cred.portal import Portal
435
portal_obj = Portal(realm, [memory_checker, file_checker, anon_checker])
436
```
437
438
### Protocol Integration
439
440
Integration points for using authentication in network protocols.
441
442
```python { .api }
443
# HTTP authentication example
444
from twisted.web.guard import HTTPAuthSessionWrapper, BasicCredentialFactory, DigestCredentialFactory
445
446
# Create credential factories
447
basic_factory = BasicCredentialFactory("My Realm")
448
digest_factory = DigestCredentialFactory("md5", "My Realm")
449
450
# Wrap resource with authentication
451
protected_resource = HTTPAuthSessionWrapper(portal_obj, [basic_factory, digest_factory])
452
453
# SSH authentication integration
454
from twisted.conch.ssh import factory
455
456
class MySSHFactory(factory.SSHFactory):
457
def __init__(self, portal):
458
self.portal = portal
459
460
def buildProtocol(self, addr):
461
protocol = factory.SSHFactory.buildProtocol(self, addr)
462
protocol.portal = self.portal
463
return protocol
464
```
465
466
### Custom Authentication
467
468
Patterns for implementing custom authentication mechanisms.
469
470
```python { .api }
471
# Custom credentials class
472
class TokenCredentials:
473
"""Custom token-based credentials."""
474
475
def __init__(self, token):
476
self.token = token
477
478
# Custom checker
479
class TokenChecker:
480
"""Custom token validation checker."""
481
482
credentialInterfaces = (TokenCredentials,)
483
484
def __init__(self, token_validator):
485
self.token_validator = token_validator
486
487
def requestAvatarId(self, credentials):
488
if self.token_validator.validate(credentials.token):
489
return defer.succeed(credentials.token.user_id)
490
else:
491
return defer.fail(error.UnauthorizedLogin("Invalid token"))
492
493
# Custom realm
494
class MyRealm:
495
"""Custom realm for creating user avatars."""
496
497
def requestAvatar(self, avatarId, mind, *interfaces):
498
if IMyUser in interfaces:
499
user = MyUser(avatarId)
500
logout = lambda: user.logout()
501
return (IMyUser, user, logout)
502
raise NotImplementedError()
503
```
504
505
**Complete Authentication Example**:
506
507
```python
508
from twisted.cred import portal, checkers, credentials
509
from twisted.internet import defer
510
from twisted.web import guard, resource, server
511
from twisted.application import internet, service
512
513
# Define user interface and avatar
514
class IUser(Interface):
515
pass
516
517
class User:
518
def __init__(self, username):
519
self.username = username
520
521
# Create realm
522
class MyRealm:
523
def requestAvatar(self, avatarId, mind, *interfaces):
524
if IUser in interfaces:
525
user = User(avatarId.decode())
526
return (IUser, user, lambda: None)
527
raise NotImplementedError()
528
529
# Set up authentication
530
realm = MyRealm()
531
checker = checkers.InMemoryUsernamePasswordDatabaseDontUse()
532
checker.addUser(b"admin", b"password")
533
534
portal_obj = portal.Portal(realm, [checker])
535
536
# Create protected web resource
537
protected_resource = resource.Resource()
538
539
# Wrap with HTTP authentication
540
credential_factory = guard.BasicCredentialFactory("Protected Area")
541
wrapper = guard.HTTPAuthSessionWrapper(portal_obj, [credential_factory])
542
543
# Add to service
544
site = server.Site(wrapper)
545
web_service = internet.TCPServer(8080, site)
546
547
# Create application
548
application = service.Application("AuthApp")
549
web_service.setServiceParent(application)
550
```