0
# Token Management
1
2
Token creation, validation, and formatting with support for Bearer tokens, MAC tokens, and JWT tokens. Includes token generators, validators, and utility functions for comprehensive token lifecycle management.
3
4
## Capabilities
5
6
### OAuth 2.0 Token
7
8
OAuth 2.0 token object providing scope management, token metadata, and validation utilities. Extends Python dictionary with OAuth-specific functionality.
9
10
```python { .api }
11
class OAuth2Token(dict[str, str]):
12
def __init__(
13
self,
14
params: dict[str, str],
15
old_scope: str | list[str] | None = None,
16
): ...
17
18
@property
19
def scope_changed(self) -> bool:
20
"""Whether scope changed from original token."""
21
22
@property
23
def old_scope(self) -> str | None:
24
"""Original token scope as string."""
25
26
@property
27
def old_scopes(self) -> list[str]:
28
"""Original token scopes as list."""
29
30
@property
31
def scope(self) -> str | None:
32
"""Current token scope as string."""
33
34
@property
35
def scopes(self) -> list[str]:
36
"""Current token scopes as list."""
37
38
@property
39
def missing_scopes(self) -> list[str]:
40
"""Scopes that were removed from original."""
41
42
@property
43
def additional_scopes(self) -> list[str]:
44
"""Scopes that were added to original."""
45
```
46
47
### Bearer Token Handler
48
49
Bearer token implementation providing token creation, validation, and request processing according to RFC 6750.
50
51
```python { .api }
52
class BearerToken:
53
def __init__(
54
self,
55
request_validator=None,
56
token_generator=None,
57
expires_in: int | None = None,
58
refresh_token_generator=None,
59
):
60
"""
61
Bearer token handler.
62
63
Parameters:
64
- request_validator: Request validator instance
65
- token_generator: Function to generate access tokens
66
- expires_in: Token expiration time in seconds
67
- refresh_token_generator: Function to generate refresh tokens
68
"""
69
70
def create_token(
71
self,
72
request,
73
refresh_token: bool = False,
74
**kwargs,
75
) -> OAuth2Token:
76
"""
77
Create new bearer token.
78
79
Parameters:
80
- request: OAuth request object
81
- refresh_token: Whether to include refresh token
82
83
Returns:
84
OAuth2Token with access token and optional refresh token
85
"""
86
87
def validate_request(self, request) -> bool:
88
"""Validate bearer token request."""
89
90
def estimate_type(self, request) -> int:
91
"""Estimate confidence that request uses bearer tokens."""
92
```
93
94
### Token Utility Functions
95
96
Utility functions for token preparation, extraction, and formatting across different authentication methods.
97
98
```python { .api }
99
def prepare_bearer_uri(token: str, uri: str) -> str:
100
"""Add bearer token to URI query parameters."""
101
102
def prepare_bearer_headers(
103
token: str,
104
headers: dict[str, str] | None = None,
105
) -> dict[str, str]:
106
"""Add bearer token to Authorization header."""
107
108
def prepare_bearer_body(token: str, body: str = "") -> str:
109
"""Add bearer token to request body."""
110
111
def get_token_from_header(request) -> str | None:
112
"""Extract bearer token from Authorization header."""
113
114
def prepare_mac_header(
115
token: str,
116
uri: str,
117
key: str | bytes | bytearray,
118
http_method: str,
119
nonce: str | None = None,
120
headers: dict[str, str] | None = None,
121
body: str | None = None,
122
ext: str = "",
123
hash_algorithm: str = "hmac-sha-1",
124
issue_time: datetime | None = None,
125
draft: int = 0,
126
) -> dict[str, str]:
127
"""Prepare MAC authentication header."""
128
```
129
130
### Token Generators
131
132
Token generation functions for creating secure access tokens and refresh tokens.
133
134
```python { .api }
135
def random_token_generator(request, refresh_token: bool = False) -> str:
136
"""Generate random token using cryptographically secure methods."""
137
138
def signed_token_generator(private_pem: str, **kwargs) -> callable:
139
"""
140
Create signed token generator using RSA private key.
141
142
Parameters:
143
- private_pem: RSA private key in PEM format
144
145
Returns:
146
Function that generates signed JWT tokens
147
"""
148
```
149
150
## Usage Examples
151
152
### Bearer Token Usage
153
154
```python
155
from oauthlib.oauth2 import BearerToken, RequestValidator
156
157
class MyRequestValidator(RequestValidator):
158
def validate_bearer_token(self, token, scopes, request):
159
# Validate bearer token from database
160
token_data = get_token_from_db(token)
161
if not token_data or token_data.expired:
162
return False
163
164
# Check if token has required scopes
165
token_scopes = token_data.scopes.split()
166
return all(scope in token_scopes for scope in scopes)
167
168
def save_bearer_token(self, token, request, *args, **kwargs):
169
# Store bearer token in database
170
store_token_in_db(token, request.user_id, request.client_id)
171
172
# Create bearer token handler
173
validator = MyRequestValidator()
174
bearer_token = BearerToken(
175
request_validator=validator,
176
expires_in=3600, # 1 hour
177
)
178
179
# Create token for authorized request
180
token = bearer_token.create_token(request, refresh_token=True)
181
# Returns: {
182
# 'access_token': 'abc123...',
183
# 'token_type': 'Bearer',
184
# 'expires_in': 3600,
185
# 'refresh_token': 'def456...',
186
# 'scope': 'read write'
187
# }
188
```
189
190
### Custom Token Generator
191
192
```python
193
import jwt
194
from datetime import datetime, timedelta
195
from oauthlib.common import generate_token
196
197
def jwt_token_generator(request):
198
"""Generate JWT access tokens."""
199
payload = {
200
'sub': request.user_id,
201
'client_id': request.client_id,
202
'scopes': request.scopes,
203
'iat': datetime.utcnow(),
204
'exp': datetime.utcnow() + timedelta(hours=1),
205
'jti': generate_token(16) # JWT ID
206
}
207
return jwt.encode(payload, 'your-secret-key', algorithm='HS256')
208
209
# Use custom generator
210
bearer_token = BearerToken(
211
request_validator=validator,
212
token_generator=jwt_token_generator,
213
refresh_token_generator=lambda req: generate_token(32)
214
)
215
```
216
217
### Token Preparation for Requests
218
219
```python
220
from oauthlib.oauth2.rfc6749.tokens import (
221
prepare_bearer_headers,
222
prepare_bearer_uri,
223
prepare_bearer_body
224
)
225
226
access_token = 'abc123def456'
227
228
# Add token to Authorization header (recommended)
229
headers = prepare_bearer_headers(access_token)
230
# {'Authorization': 'Bearer abc123def456'}
231
232
# Add token to URI query (less secure)
233
uri = prepare_bearer_uri(access_token, 'https://api.example.com/data')
234
# 'https://api.example.com/data?access_token=abc123def456'
235
236
# Add token to request body (for POST requests)
237
body = prepare_bearer_body(access_token, 'data=value')
238
# 'data=value&access_token=abc123def456'
239
```
240
241
### Token Validation
242
243
```python
244
from oauthlib.oauth2.rfc6749.tokens import get_token_from_header
245
246
def validate_api_request(request):
247
"""Validate API request with bearer token."""
248
249
# Extract token from request
250
token = get_token_from_header(request)
251
if not token:
252
return False, "Missing access token"
253
254
# Validate token
255
token_data = get_token_from_database(token)
256
if not token_data:
257
return False, "Invalid access token"
258
259
if token_data.expired:
260
return False, "Access token expired"
261
262
# Check scopes for this endpoint
263
required_scopes = ['api:read']
264
token_scopes = token_data.scopes.split()
265
if not all(scope in token_scopes for scope in required_scopes):
266
return False, "Insufficient scope"
267
268
return True, token_data
269
```
270
271
### OAuth2Token Usage
272
273
```python
274
from oauthlib.oauth2.rfc6749.tokens import OAuth2Token
275
276
# Create token from server response
277
response_data = {
278
'access_token': 'abc123',
279
'token_type': 'Bearer',
280
'expires_in': 3600,
281
'refresh_token': 'def456',
282
'scope': 'read write admin'
283
}
284
285
token = OAuth2Token(response_data, old_scope='read write')
286
287
# Check scope changes
288
print(token.scope_changed) # True (admin scope added)
289
print(token.scopes) # ['read', 'write', 'admin']
290
print(token.old_scopes) # ['read', 'write']
291
print(token.additional_scopes) # ['admin']
292
print(token.missing_scopes) # []
293
294
# Token acts like a dictionary
295
print(token['access_token']) # 'abc123'
296
print(token.get('expires_in')) # 3600
297
```
298
299
### MAC Token Authentication
300
301
```python
302
from oauthlib.oauth2.rfc6749.tokens import prepare_mac_header
303
import datetime
304
305
# Prepare MAC authentication header
306
mac_header = prepare_mac_header(
307
token='h480djs93hd8',
308
uri='https://api.example.com/data',
309
key='secret-mac-key',
310
http_method='GET',
311
nonce='unique-nonce-123',
312
hash_algorithm='hmac-sha-256',
313
issue_time=datetime.datetime.utcnow()
314
)
315
316
print(mac_header)
317
# {
318
# 'Authorization': 'MAC id="h480djs93hd8", nonce="unique-nonce-123",
319
# ts="1234567890", mac="signature..."'
320
# }
321
```
322
323
## Token Lifecycle Management
324
325
### Token Refresh Flow
326
327
```python
328
def refresh_access_token(refresh_token, client_id, client_secret):
329
"""Refresh an expired access token."""
330
from oauthlib.oauth2 import WebApplicationClient
331
import requests
332
333
client = WebApplicationClient(client_id)
334
335
# Prepare refresh request
336
token_url, headers, body = client.prepare_refresh_token_request(
337
'https://auth.example.com/token',
338
refresh_token=refresh_token,
339
scope=['read', 'write'] # Optional: request different scopes
340
)
341
342
# Add client authentication
343
headers['Authorization'] = f'Basic {base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()}'
344
345
# Make request
346
response = requests.post(token_url, headers=headers, data=body)
347
348
if response.status_code == 200:
349
return client.parse_request_body_response(response.text)
350
else:
351
raise Exception(f"Token refresh failed: {response.text}")
352
```
353
354
### Token Revocation
355
356
```python
357
def revoke_token(token, token_type_hint, client_id, client_secret):
358
"""Revoke an access or refresh token."""
359
from oauthlib.oauth2 import WebApplicationClient
360
import requests
361
362
client = WebApplicationClient(client_id)
363
364
# Prepare revocation request
365
revoke_url, headers, body = client.prepare_token_revocation_request(
366
'https://auth.example.com/revoke',
367
token=token,
368
token_type_hint=token_type_hint # 'access_token' or 'refresh_token'
369
)
370
371
# Add client authentication
372
headers['Authorization'] = f'Basic {base64.b64encode(f"{client_id}:{client_secret}".encode()).decode()}'
373
374
# Make request
375
response = requests.post(revoke_url, headers=headers, data=body)
376
377
return response.status_code == 200
378
```