0
# Core OAuth Operations
1
2
Essential OAuth 1.0 functionality providing consumer and token management, request construction, parameter normalization, and signature generation. These core components form the foundation for all OAuth authentication workflows.
3
4
## Capabilities
5
6
### Consumer Management
7
8
OAuth consumers represent third-party applications that want to access protected resources. The Consumer class manages application credentials and provides string serialization for debugging.
9
10
```python { .api }
11
class Consumer:
12
def __init__(self, key: str, secret: str):
13
"""
14
Initialize OAuth consumer with application credentials.
15
16
Args:
17
key (str): Consumer key from service provider
18
secret (str): Consumer secret from service provider
19
20
Raises:
21
ValueError: If key or secret is None
22
"""
23
24
def __str__(self) -> str:
25
"""Return URL-encoded string representation of consumer credentials."""
26
```
27
28
### Token Management
29
30
OAuth tokens represent user authorization credentials, including both request tokens (for authorization) and access tokens (for accessing protected resources).
31
32
```python { .api }
33
class Token:
34
def __init__(self, key: str, secret: str):
35
"""
36
Initialize OAuth token with user credentials.
37
38
Args:
39
key (str): Token key from OAuth flow
40
secret (str): Token secret from OAuth flow
41
42
Raises:
43
ValueError: If key or secret is None
44
"""
45
46
def set_callback(self, callback: str):
47
"""
48
Set callback URL for OAuth 1.0a flow.
49
50
Args:
51
callback (str): Callback URL for authorization
52
"""
53
54
def set_verifier(self, verifier: str = None):
55
"""
56
Set OAuth verifier for token exchange.
57
58
Args:
59
verifier (str, optional): OAuth verifier. If None, generates random verifier.
60
"""
61
62
def get_callback_url(self) -> str:
63
"""
64
Get callback URL with oauth_verifier parameter appended.
65
66
Returns:
67
str: Callback URL with verifier parameter
68
"""
69
70
def to_string(self) -> str:
71
"""
72
Serialize token to URL-encoded string including secret.
73
74
Returns:
75
str: Token serialized as query parameters
76
"""
77
78
@staticmethod
79
def from_string(s: str):
80
"""
81
Deserialize token from URL-encoded string.
82
83
Args:
84
s (str): URL-encoded token string
85
86
Returns:
87
Token: Deserialized token object
88
89
Raises:
90
ValueError: If string format is invalid or missing required parameters
91
"""
92
93
def __str__(self) -> str:
94
"""Return string representation of token."""
95
```
96
97
### Request Construction and Signing
98
99
The Request class manages OAuth request parameters, handles normalization, and coordinates the signing process. It extends Python's dict to provide parameter access.
100
101
```python { .api }
102
class Request(dict):
103
def __init__(self, method: str = 'GET', url: str = None, parameters: dict = None, body: bytes = b'', is_form_encoded: bool = False):
104
"""
105
Initialize OAuth request with HTTP parameters.
106
107
Args:
108
method (str): HTTP method (default: 'GET')
109
url (str): Request URL
110
parameters (dict): Request parameters
111
body (bytes): Request body for POST requests
112
is_form_encoded (bool): Whether body is form-encoded
113
"""
114
115
def get_nonoauth_parameters(self) -> dict:
116
"""
117
Extract non-OAuth parameters from request.
118
119
Returns:
120
dict: Parameters not starting with 'oauth_'
121
"""
122
123
def to_header(self, realm: str = '') -> dict:
124
"""
125
Serialize OAuth parameters as Authorization header.
126
127
Args:
128
realm (str): OAuth realm parameter
129
130
Returns:
131
dict: Dictionary with 'Authorization' header
132
"""
133
134
def to_postdata(self) -> str:
135
"""
136
Serialize all parameters as POST body data.
137
138
Returns:
139
str: URL-encoded parameter string
140
"""
141
142
def to_url(self) -> str:
143
"""
144
Serialize parameters as URL query string for GET requests.
145
146
Returns:
147
str: Complete URL with parameters
148
"""
149
150
def get_parameter(self, parameter: str):
151
"""
152
Get specific parameter value.
153
154
Args:
155
parameter (str): Parameter name
156
157
Returns:
158
Parameter value
159
160
Raises:
161
Error: If parameter not found
162
"""
163
164
def get_normalized_parameters(self) -> str:
165
"""
166
Generate normalized parameter string for signature base.
167
168
Returns:
169
str: Normalized parameters per OAuth spec
170
"""
171
172
def sign_request(self, signature_method, consumer, token):
173
"""
174
Sign the request using specified signature method.
175
176
Args:
177
signature_method: Signature method instance
178
consumer: Consumer credentials
179
token: Token credentials (optional)
180
"""
181
182
@classmethod
183
def make_timestamp(cls) -> str:
184
"""
185
Generate OAuth timestamp (seconds since epoch).
186
187
Returns:
188
str: Current timestamp
189
"""
190
191
@classmethod
192
def make_nonce(cls) -> str:
193
"""
194
Generate OAuth nonce (random number).
195
196
Returns:
197
str: Random nonce value
198
"""
199
200
@classmethod
201
def from_request(cls, http_method: str, http_url: str, headers: dict = None, parameters: dict = None, query_string: str = None):
202
"""
203
Create Request from HTTP request components.
204
205
Args:
206
http_method (str): HTTP method
207
http_url (str): Request URL
208
headers (dict): HTTP headers
209
parameters (dict): Request parameters
210
query_string (str): URL query string
211
212
Returns:
213
Request: Request object or None if no OAuth parameters
214
"""
215
216
@classmethod
217
def from_consumer_and_token(cls, consumer, token=None, http_method: str = 'GET', http_url: str = None, parameters: dict = None, body: bytes = b'', is_form_encoded: bool = False):
218
"""
219
Create Request from consumer and token credentials.
220
221
Args:
222
consumer: Consumer credentials
223
token: Token credentials (optional)
224
http_method (str): HTTP method
225
http_url (str): Request URL
226
parameters (dict): Additional parameters
227
body (bytes): Request body
228
is_form_encoded (bool): Whether body is form-encoded
229
230
Returns:
231
Request: Configured request object
232
"""
233
234
@classmethod
235
def from_token_and_callback(cls, token, callback: str = None, http_method: str = 'GET', http_url: str = None, parameters: dict = None):
236
"""
237
Create Request from token and callback for authorization flow.
238
239
Args:
240
token: Token credentials
241
callback (str): Callback URL
242
http_method (str): HTTP method
243
http_url (str): Request URL
244
parameters (dict): Additional parameters
245
246
Returns:
247
Request: Configured request object
248
"""
249
```
250
251
### Signature Methods
252
253
OAuth signature methods provide pluggable signing algorithms. The library includes HMAC-SHA1 (recommended) and PLAINTEXT methods.
254
255
```python { .api }
256
class SignatureMethod:
257
"""Abstract base class for signature methods."""
258
259
def signing_base(self, request, consumer, token) -> tuple:
260
"""
261
Calculate the signature base string and signing key.
262
263
Args:
264
request: Request object
265
consumer: Consumer credentials
266
token: Token credentials
267
268
Returns:
269
tuple: (signing_key, base_string)
270
"""
271
272
def sign(self, request, consumer, token) -> bytes:
273
"""
274
Generate signature for the request.
275
276
Args:
277
request: Request object
278
consumer: Consumer credentials
279
token: Token credentials
280
281
Returns:
282
bytes: Generated signature
283
"""
284
285
def check(self, request, consumer, token, signature: str) -> bool:
286
"""
287
Verify signature against request.
288
289
Args:
290
request: Request object
291
consumer: Consumer credentials
292
token: Token credentials
293
signature (str): Signature to verify
294
295
Returns:
296
bool: True if signature is valid
297
"""
298
299
class SignatureMethod_HMAC_SHA1(SignatureMethod):
300
"""HMAC-SHA1 signature method (recommended)."""
301
name = 'HMAC-SHA1'
302
303
def signing_base(self, request, consumer, token) -> tuple:
304
"""Calculate HMAC-SHA1 signing base and key."""
305
306
def sign(self, request, consumer, token) -> bytes:
307
"""Generate HMAC-SHA1 signature."""
308
309
class SignatureMethod_PLAINTEXT(SignatureMethod):
310
"""PLAINTEXT signature method (less secure)."""
311
name = 'PLAINTEXT'
312
313
def signing_base(self, request, consumer, token) -> tuple:
314
"""Calculate PLAINTEXT signing base and key."""
315
316
def sign(self, request, consumer, token) -> bytes:
317
"""Generate PLAINTEXT signature."""
318
```
319
320
### Utility Functions
321
322
Helper functions for common OAuth operations including parameter generation, string encoding, and authentication headers.
323
324
```python { .api }
325
def build_authenticate_header(realm: str = '') -> dict:
326
"""
327
Build WWW-Authenticate header for 401 responses.
328
329
Args:
330
realm (str): OAuth realm parameter
331
332
Returns:
333
dict: Header dictionary with WWW-Authenticate
334
"""
335
336
def build_xoauth_string(url: str, consumer, token=None) -> str:
337
"""
338
Build XOAUTH string for SMTP/IMAP authentication.
339
340
Args:
341
url (str): Service URL
342
consumer: Consumer credentials
343
token: Token credentials (optional)
344
345
Returns:
346
str: XOAUTH authentication string
347
"""
348
349
def escape(s: str) -> str:
350
"""
351
URL escape string including forward slashes.
352
353
Args:
354
s (str): String to escape
355
356
Returns:
357
str: URL-escaped string
358
"""
359
360
def generate_timestamp() -> int:
361
"""
362
Generate OAuth timestamp (seconds since epoch).
363
364
Returns:
365
int: Current timestamp
366
"""
367
368
def generate_nonce(length: int = 8) -> str:
369
"""
370
Generate pseudorandom nonce.
371
372
Args:
373
length (int): Nonce length in digits
374
375
Returns:
376
str: Random numeric string
377
"""
378
379
def generate_verifier(length: int = 8) -> str:
380
"""
381
Generate pseudorandom verifier for OAuth 1.0a.
382
383
Args:
384
length (int): Verifier length in digits
385
386
Returns:
387
str: Random numeric string
388
"""
389
390
def to_unicode(s) -> str:
391
"""
392
Convert to unicode with proper error handling.
393
394
Args:
395
s: String or bytes to convert
396
397
Returns:
398
str: Unicode string
399
400
Raises:
401
TypeError: If input is not string or bytes, or contains invalid UTF-8
402
"""
403
404
def to_utf8(s) -> bytes:
405
"""
406
Convert unicode string to UTF-8 bytes.
407
408
Args:
409
s: String to convert
410
411
Returns:
412
bytes: UTF-8 encoded bytes
413
"""
414
415
def to_unicode_if_string(s):
416
"""
417
Convert to unicode only if input is a string type.
418
419
Args:
420
s: Value to potentially convert
421
422
Returns:
423
Unicode string if input was string, otherwise unchanged
424
"""
425
426
def to_utf8_if_string(s):
427
"""
428
Convert to UTF-8 bytes only if input is a string type.
429
430
Args:
431
s: Value to potentially convert
432
433
Returns:
434
UTF-8 bytes if input was string, otherwise unchanged
435
"""
436
437
def to_unicode_optional_iterator(x):
438
"""
439
Convert string or iterable of strings to unicode.
440
441
Args:
442
x: String or iterable to convert
443
444
Returns:
445
Unicode string or list of unicode strings
446
447
Raises:
448
TypeError: If contains invalid UTF-8
449
"""
450
451
def to_utf8_optional_iterator(x):
452
"""
453
Convert string or iterable of strings to UTF-8 bytes.
454
455
Args:
456
x: String or iterable to convert
457
458
Returns:
459
UTF-8 bytes or list of UTF-8 byte strings
460
"""
461
```
462
463
## Usage Examples
464
465
### Basic Request Signing
466
467
```python
468
import oauth2
469
470
# Create credentials
471
consumer = oauth2.Consumer('consumer_key', 'consumer_secret')
472
token = oauth2.Token('token_key', 'token_secret')
473
474
# Create and sign request
475
request = oauth2.Request.from_consumer_and_token(
476
consumer=consumer,
477
token=token,
478
http_method='GET',
479
http_url='https://api.example.com/data'
480
)
481
482
signature_method = oauth2.SignatureMethod_HMAC_SHA1()
483
request.sign_request(signature_method, consumer, token)
484
485
# Get authorization header
486
headers = request.to_header()
487
print(headers['Authorization'])
488
```
489
490
### Token Serialization
491
492
```python
493
import oauth2
494
495
# Create token
496
token = oauth2.Token('token_key', 'token_secret')
497
token.set_callback('https://myapp.com/callback')
498
token.set_verifier('verification_code')
499
500
# Serialize for storage
501
token_string = token.to_string()
502
503
# Deserialize from storage
504
restored_token = oauth2.Token.from_string(token_string)
505
```
506
507
### String Encoding Utilities
508
509
```python
510
import oauth2
511
512
# Handle different string types for OAuth parameters
513
raw_data = b'some bytes data'
514
unicode_data = oauth2.to_unicode(raw_data) # Convert to unicode
515
utf8_data = oauth2.to_utf8(unicode_data) # Convert back to UTF-8
516
517
# Conditional conversion
518
mixed_data = ['string1', b'bytes2', 'string3']
519
converted = [oauth2.to_unicode_if_string(item) for item in mixed_data]
520
521
# Handle iterables
522
parameter_list = ['param1', 'param2', 'param3']
523
unicode_params = oauth2.to_unicode_optional_iterator(parameter_list)
524
```