0
# Authentication and Token Management
1
2
Core authentication functionality for AWS Cognito User Pools, providing secure user authentication using SRP protocol, admin authentication, token verification, automatic renewal, and logout operations. This module handles the complete authentication lifecycle from initial login through token management and secure logout.
3
4
## Capabilities
5
6
### SRP Authentication
7
8
Authenticate users using the Secure Remote Password (SRP) protocol, which provides secure authentication without transmitting passwords over the network. This is the recommended authentication method.
9
10
```python { .api }
11
def authenticate(self, password: str, client_metadata: dict = None) -> None:
12
"""
13
Authenticate user using the SRP protocol.
14
15
Args:
16
password (str): The user's password
17
client_metadata (dict, optional): Metadata for custom workflows
18
19
Raises:
20
MFAChallengeException: When MFA is required
21
ForceChangePasswordException: When password change is required
22
23
Sets instance attributes:
24
- id_token: JWT ID token
25
- access_token: JWT access token
26
- refresh_token: Token for refreshing access
27
- token_type: Type of token (usually "Bearer")
28
- id_claims: Verified claims from ID token
29
- access_claims: Verified claims from access token
30
"""
31
```
32
33
**Usage Example:**
34
35
```python
36
from pycognito import Cognito
37
from pycognito.exceptions import MFAChallengeException
38
39
u = Cognito('your-user-pool-id', 'your-client-id', username='bob')
40
41
try:
42
u.authenticate(password='bobs-password')
43
print("Authentication successful!")
44
print(f"Access token: {u.access_token}")
45
except MFAChallengeException as e:
46
# Handle MFA challenge
47
mfa_tokens = e.get_tokens()
48
# Proceed with MFA flow
49
```
50
51
### Admin Authentication
52
53
Authenticate users using administrative privileges without SRP protocol. This method bypasses SRP but requires admin permissions on the user pool.
54
55
```python { .api }
56
def admin_authenticate(self, password: str) -> None:
57
"""
58
Authenticate user using admin super privileges.
59
60
Args:
61
password (str): The user's password
62
63
Sets same instance attributes as authenticate()
64
"""
65
```
66
67
**Usage Example:**
68
69
```python
70
u = Cognito('your-user-pool-id', 'your-client-id', username='bob')
71
u.admin_authenticate(password='bobs-password')
72
```
73
74
### New Password Challenge
75
76
Handle forced password change scenarios when users are required to set a new password after initial authentication or admin password reset.
77
78
```python { .api }
79
def new_password_challenge(self, password: str, new_password: str) -> None:
80
"""
81
Handle NEW_PASSWORD_REQUIRED challenge by setting a new password.
82
83
Args:
84
password (str): The user's current/temporary password
85
new_password (str): The new password to set
86
87
Raises:
88
Exception: If the challenge response fails
89
90
Sets instance attributes:
91
- id_token: JWT ID token
92
- access_token: JWT access token
93
- refresh_token: Token for refreshing access
94
- token_type: Type of token (usually "Bearer")
95
- id_claims: Verified claims from ID token
96
- access_claims: Verified claims from access token
97
"""
98
```
99
100
**Usage Example:**
101
102
```python
103
from pycognito import Cognito
104
from pycognito.exceptions import ForceChangePasswordException
105
106
u = Cognito('your-user-pool-id', 'your-client-id', username='bob')
107
108
try:
109
u.authenticate(password='temporary-password')
110
except ForceChangePasswordException:
111
# User must change their password
112
u.new_password_challenge(
113
password='temporary-password',
114
new_password='new-secure-password'
115
)
116
print("Password changed successfully!")
117
print(f"Access token: {u.access_token}")
118
```
119
120
### Token Verification
121
122
Verify the authenticity and validity of JWT tokens received from authentication or stored from previous sessions.
123
124
```python { .api }
125
def verify_tokens(self) -> None:
126
"""
127
Verify the current id_token and access_token.
128
129
Raises:
130
TokenVerificationException: If tokens fail verification
131
132
Verifies:
133
- Token signatures using JWK keys
134
- Token expiration times
135
- Token audience and issuer
136
- Token use claims
137
"""
138
139
def verify_token(self, token: str, id_name: str, token_use: str) -> dict:
140
"""
141
Verify a specific token.
142
143
Args:
144
token (str): The JWT token to verify
145
id_name (str): Token identifier ("id_token" or "access_token")
146
token_use (str): Expected token use ("id" or "access")
147
148
Returns:
149
dict: Verified token payload
150
151
Raises:
152
TokenVerificationException: If token verification fails
153
"""
154
```
155
156
**Usage Example:**
157
158
```python
159
# Verify tokens from a previous session
160
u = Cognito(
161
'your-user-pool-id',
162
'your-client-id',
163
id_token='existing-id-token',
164
access_token='existing-access-token',
165
refresh_token='existing-refresh-token'
166
)
167
168
try:
169
u.verify_tokens() # Throws exception if invalid
170
print("Tokens are valid!")
171
print(f"User ID: {u.id_claims['sub']}")
172
print(f"Username: {u.access_claims['username']}")
173
except TokenVerificationException:
174
print("Tokens are invalid or expired")
175
```
176
177
### Token Expiration and Renewal
178
179
Check token expiration status and automatically renew access tokens using refresh tokens.
180
181
```python { .api }
182
def check_token(self, renew: bool = True) -> bool:
183
"""
184
Check if access token has expired and optionally renew it.
185
186
Args:
187
renew (bool): Whether to automatically renew expired tokens
188
189
Returns:
190
bool: True if token was expired, False if still valid
191
192
Raises:
193
AttributeError: If no access token is available
194
"""
195
196
def renew_access_token(self) -> None:
197
"""
198
Set a new access token using the cached refresh token.
199
200
Raises:
201
Exception: If refresh token is invalid or expired
202
203
Updates:
204
- access_token: New access token
205
- id_token: New ID token
206
- token_type: Token type
207
- access_claims: New access token claims
208
- id_claims: New ID token claims
209
"""
210
```
211
212
**Usage Example:**
213
214
```python
215
# Check and renew token automatically
216
if u.check_token(renew=True):
217
print("Token was expired and has been renewed")
218
else:
219
print("Token is still valid")
220
221
# Manual token renewal
222
u.renew_access_token()
223
print(f"New access token: {u.access_token}")
224
```
225
226
### Logout
227
228
Securely log out users by invalidating all tokens across all clients and clearing local token storage.
229
230
```python { .api }
231
def logout(self) -> None:
232
"""
233
Log user out of all clients and remove token attributes.
234
235
Actions:
236
- Calls AWS Cognito global sign out
237
- Clears id_token, refresh_token, access_token, token_type
238
- Invalidates tokens on all devices/clients
239
"""
240
```
241
242
**Usage Example:**
243
244
```python
245
# Logout user
246
u.logout()
247
print("User logged out successfully")
248
249
# Tokens are now None
250
assert u.access_token is None
251
assert u.id_token is None
252
assert u.refresh_token is None
253
```
254
255
### JWT Key Management
256
257
Retrieve and cache JSON Web Key (JWK) sets for token verification.
258
259
```python { .api }
260
def get_keys(self) -> dict:
261
"""
262
Get JWK keys for token verification.
263
264
Returns:
265
dict: JWK key set from AWS Cognito or environment
266
267
Checks:
268
1. Environment variable COGNITO_JWKS
269
2. AWS Cognito /.well-known/jwks.json endpoint
270
"""
271
272
def get_key(self, kid: str) -> dict:
273
"""
274
Get specific JWK key by key ID.
275
276
Args:
277
kid (str): Key ID from JWT header
278
279
Returns:
280
dict: JWK key data
281
"""
282
```
283
284
### Session Management
285
286
Switch boto3 sessions for testing or different AWS configurations.
287
288
```python { .api }
289
def switch_session(self, session) -> None:
290
"""
291
Switch the boto3 session used for Cognito operations.
292
293
Args:
294
session: boto3 session object
295
296
Used primarily for:
297
- Unit testing with placebo library
298
- Different AWS credentials/regions
299
- Custom boto3 configurations
300
"""
301
```
302
303
## Usage Patterns
304
305
### Basic Authentication Flow
306
307
```python
308
from pycognito import Cognito
309
310
# Initialize
311
u = Cognito('pool-id', 'client-id', username='user')
312
313
# Authenticate
314
u.authenticate(password='password')
315
316
# Use tokens
317
headers = {'Authorization': f'Bearer {u.access_token}'}
318
319
# Check token before use
320
if not u.check_token():
321
# Token is still valid
322
make_api_call(headers)
323
```
324
325
### Persistent Session Management
326
327
```python
328
# Save tokens after authentication
329
session_data = {
330
'id_token': u.id_token,
331
'access_token': u.access_token,
332
'refresh_token': u.refresh_token
333
}
334
335
# Later, restore session
336
u = Cognito(
337
'pool-id', 'client-id',
338
id_token=session_data['id_token'],
339
access_token=session_data['access_token'],
340
refresh_token=session_data['refresh_token']
341
)
342
343
# Verify and potentially renew
344
try:
345
u.verify_tokens()
346
except TokenVerificationException:
347
# Handle invalid tokens
348
redirect_to_login()
349
```
350
351
### MFA Handling
352
353
```python
354
from pycognito.exceptions import (
355
MFAChallengeException,
356
SoftwareTokenMFAChallengeException,
357
SMSMFAChallengeException
358
)
359
360
try:
361
u.authenticate(password='password')
362
except SoftwareTokenMFAChallengeException as e:
363
# Handle TOTP MFA
364
code = input("Enter TOTP code: ")
365
u.respond_to_software_token_mfa_challenge(code, e.get_tokens())
366
except SMSMFAChallengeException as e:
367
# Handle SMS MFA
368
code = input("Enter SMS code: ")
369
u.respond_to_sms_mfa_challenge(code, e.get_tokens())
370
```