0
# OAuth 1.0 Implementation
1
2
Complete OAuth 1.0 (RFC 5849) client and server implementation supporting the full three-legged authentication flow. Includes request token acquisition, user authorization, access token exchange, and protected resource access with multiple signature methods.
3
4
## Capabilities
5
6
### OAuth 1.0 Client
7
8
OAuth 1.0 client for signing requests and managing the authentication flow. Supports multiple signature methods including HMAC-SHA1, HMAC-SHA256, HMAC-SHA512, RSA-SHA1, RSA-SHA256, RSA-SHA512, and PLAINTEXT.
9
10
```python { .api }
11
class Client:
12
def __init__(
13
self,
14
client_key: str,
15
client_secret: str | None = None,
16
resource_owner_key=None,
17
resource_owner_secret=None,
18
callback_uri=None,
19
signature_method: str = "HMAC-SHA1",
20
signature_type: str = "AUTH_HEADER",
21
rsa_key=None,
22
verifier=None,
23
realm=None,
24
encoding: str = "utf-8",
25
decoding=None,
26
nonce=None,
27
timestamp=None,
28
):
29
"""
30
OAuth 1.0 client for request signing and token management.
31
32
Parameters:
33
- client_key: Client identifier
34
- client_secret: Client secret for HMAC signatures
35
- resource_owner_key: Resource owner token (request or access token)
36
- resource_owner_secret: Resource owner token secret
37
- callback_uri: Callback URI for authorization
38
- signature_method: Signature method (HMAC-SHA1, RSA-SHA1, PLAINTEXT, etc.)
39
- signature_type: Where to place signature (AUTH_HEADER, QUERY, BODY)
40
- rsa_key: RSA private key for RSA signatures
41
- verifier: Authorization verifier code
42
- realm: Authorization realm
43
- encoding: String encoding
44
- nonce: Custom nonce generator
45
- timestamp: Custom timestamp generator
46
"""
47
48
def sign(
49
self,
50
uri: str,
51
http_method: str = "GET",
52
body: str | dict[str, str] | list[tuple[str, str]] | None = None,
53
headers: dict[str, str] | None = None,
54
realm=None,
55
):
56
"""
57
Sign an OAuth 1.0 request.
58
59
Parameters:
60
- uri: Request URI
61
- http_method: HTTP method (GET, POST, etc.)
62
- body: Request body
63
- headers: Request headers
64
- realm: Authorization realm
65
66
Returns:
67
Tuple of (uri, headers, body) with OAuth signature applied
68
"""
69
70
def get_oauth_signature(self, request):
71
"""Get OAuth signature for a request."""
72
73
def get_oauth_params(self, request):
74
"""Get OAuth parameters for a request."""
75
76
@classmethod
77
def register_signature_method(cls, method_name: str, method_callback):
78
"""Register a custom signature method."""
79
```
80
81
Usage example:
82
83
```python
84
from oauthlib.oauth1 import Client
85
86
# Create client with consumer credentials
87
client = Client(
88
'your-client-key',
89
client_secret='your-client-secret'
90
)
91
92
# Sign a request
93
uri, headers, body = client.sign(
94
'https://api.example.com/data',
95
http_method='GET'
96
)
97
98
# Make signed request
99
import requests
100
response = requests.get(uri, headers=headers)
101
```
102
103
### Request Token Endpoint
104
105
Server endpoint for handling OAuth 1.0 request token requests. Issues temporary credentials that clients use to obtain authorization from resource owners.
106
107
```python { .api }
108
class RequestTokenEndpoint:
109
def __init__(self, request_validator): ...
110
111
def create_request_token(self, request, credentials):
112
"""
113
Create a request token.
114
115
Parameters:
116
- request: OAuth request object
117
- credentials: Server credentials
118
119
Returns:
120
OAuth token dictionary
121
"""
122
123
def create_request_token_response(
124
self,
125
uri: str,
126
http_method: str = "GET",
127
body: str | None = None,
128
headers: dict[str, str] | None = None,
129
credentials: dict[str, str] | None = None,
130
):
131
"""Create request token endpoint response."""
132
133
def validate_request_token_request(self, request):
134
"""Validate request token request."""
135
```
136
137
### Authorization Endpoint
138
139
Server endpoint for handling OAuth 1.0 authorization requests. Manages user authorization and verifier code generation.
140
141
```python { .api }
142
class AuthorizationEndpoint:
143
def __init__(self, request_validator): ...
144
145
def create_verifier(self, request, credentials):
146
"""Create authorization verifier."""
147
148
def create_authorization_response(
149
self,
150
uri: str,
151
http_method: str = "GET",
152
body: str | None = None,
153
headers: dict[str, str] | None = None,
154
realms: list[str] | None = None,
155
credentials: dict[str, str] | None = None,
156
):
157
"""Create authorization endpoint response."""
158
159
def get_realms_and_credentials(
160
self,
161
uri: str,
162
http_method: str = "GET",
163
body: str | None = None,
164
headers: dict[str, str] | None = None,
165
):
166
"""Get authorization realms and credentials."""
167
```
168
169
### Access Token Endpoint
170
171
Server endpoint for handling OAuth 1.0 access token requests. Exchanges authorized request tokens for access tokens that can access protected resources.
172
173
```python { .api }
174
class AccessTokenEndpoint:
175
def __init__(self, request_validator): ...
176
177
def create_access_token(self, request, credentials):
178
"""Create an access token."""
179
180
def create_access_token_response(
181
self,
182
uri: str,
183
http_method: str = "GET",
184
body: str | None = None,
185
headers: dict[str, str] | None = None,
186
credentials: dict[str, str] | None = None,
187
):
188
"""Create access token endpoint response."""
189
190
def validate_access_token_request(self, request):
191
"""Validate access token request."""
192
```
193
194
### Resource Endpoint
195
196
Server endpoint for validating OAuth 1.0 signed requests to protected resources. Verifies access tokens and signatures before granting access to protected resources.
197
198
```python { .api }
199
class ResourceEndpoint:
200
def __init__(self, request_validator): ...
201
202
def validate_protected_resource_request(
203
self,
204
uri: str,
205
http_method: str = "GET",
206
body: str | None = None,
207
headers: dict[str, str] | None = None,
208
realms: list[str] | None = None,
209
) -> tuple[bool, dict]:
210
"""
211
Validate request to protected resource.
212
213
Returns:
214
Tuple of (valid, request) where valid is boolean and request contains OAuth params
215
"""
216
```
217
218
### Web Application Server
219
220
Pre-configured OAuth 1.0 server combining all endpoints for web application flows. Provides a complete server implementation with request token, authorization, access token, and resource protection capabilities.
221
222
```python { .api }
223
class WebApplicationServer:
224
def __init__(self, request_validator): ...
225
226
# Inherits all methods from RequestTokenEndpoint, AuthorizationEndpoint,
227
# AccessTokenEndpoint, and ResourceEndpoint
228
```
229
230
### Request Validator
231
232
OAuth 1.0 request validation interface that must be implemented to provide custom authentication and authorization logic. Handles client verification, token management, and security policies.
233
234
```python { .api }
235
class RequestValidator:
236
# Configuration properties
237
allowed_signature_methods: list[str]
238
safe_characters: set[str]
239
client_key_length: tuple[int, int]
240
request_token_length: tuple[int, int]
241
access_token_length: tuple[int, int]
242
timestamp_lifetime: int
243
nonce_length: tuple[int, int]
244
verifier_length: tuple[int, int]
245
realms: list[str]
246
enforce_ssl: bool
247
248
# Dummy values for timing attack protection
249
dummy_client: str
250
dummy_request_token: str
251
dummy_access_token: str
252
253
# Client validation
254
def validate_client_key(self, client_key: str, request) -> bool:
255
"""Validate client key exists and is valid."""
256
257
def check_client_key(self, client_key: str) -> bool:
258
"""Check client key format."""
259
260
def get_client_secret(self, client_key: str, request) -> str:
261
"""Get client secret for HMAC signatures."""
262
263
def get_rsa_key(self, client_key: str, request) -> str:
264
"""Get RSA public key for RSA signature verification."""
265
266
# Request token validation
267
def validate_request_token(self, client_key: str, token: str, request) -> bool:
268
"""Validate request token."""
269
270
def check_request_token(self, request_token: str) -> bool:
271
"""Check request token format."""
272
273
def get_request_token_secret(self, client_key: str, token: str, request) -> str:
274
"""Get request token secret."""
275
276
def save_request_token(self, token: dict, request) -> None:
277
"""Store request token."""
278
279
def invalidate_request_token(self, client_key: str, request_token: str, request) -> None:
280
"""Invalidate used request token."""
281
282
# Access token validation
283
def validate_access_token(self, client_key: str, token: str, request) -> bool:
284
"""Validate access token."""
285
286
def check_access_token(self, access_token: str) -> bool:
287
"""Check access token format."""
288
289
def get_access_token_secret(self, client_key: str, token: str, request) -> str:
290
"""Get access token secret."""
291
292
def save_access_token(self, token: dict, request) -> None:
293
"""Store access token."""
294
295
# Authorization validation
296
def validate_timestamp_and_nonce(
297
self,
298
client_key: str,
299
timestamp: str,
300
nonce: str,
301
request_token: str = None,
302
access_token: str = None,
303
) -> bool:
304
"""Validate timestamp and nonce to prevent replay attacks."""
305
306
def validate_redirect_uri(self, client_key: str, redirect_uri: str, request) -> bool:
307
"""Validate redirect URI."""
308
309
def validate_verifier(self, client_key: str, token: str, verifier: str, request) -> bool:
310
"""Validate authorization verifier."""
311
312
def save_verifier(self, token: str, verifier: str, request) -> None:
313
"""Store authorization verifier."""
314
315
def get_redirect_uri(self, token: str, request) -> str:
316
"""Get redirect URI for token."""
317
318
# Realm validation
319
def validate_requested_realms(self, client_key: str, realms: list[str], request) -> bool:
320
"""Validate requested authorization realms."""
321
322
def validate_realms(
323
self,
324
client_key: str,
325
token: str,
326
request,
327
uri: str = None,
328
realms: list[str] = None,
329
) -> bool:
330
"""Validate access to realms."""
331
332
def get_default_realms(self, client_key: str, request) -> list[str]:
333
"""Get default realms for client."""
334
335
def get_realms(self, token: str, request) -> list[str]:
336
"""Get realms associated with token."""
337
338
def check_realms(self, realms: list[str]) -> bool:
339
"""Check realm format."""
340
341
# Format checking
342
def check_nonce(self, nonce: str) -> bool:
343
"""Check nonce format."""
344
345
def check_verifier(self, verifier: str) -> bool:
346
"""Check verifier format."""
347
```
348
349
### Signature Methods
350
351
OAuth 1.0 signature method implementations for request authentication. Supports HMAC-based and RSA-based signatures with multiple hash algorithms.
352
353
```python { .api }
354
# Signature base string creation
355
def signature_base_string(
356
http_method: str,
357
base_str_uri: str,
358
normalized_encoded_request_parameters: str,
359
) -> str:
360
"""Create OAuth 1.0 signature base string."""
361
362
def base_string_uri(uri: str, host: str = None) -> str:
363
"""Normalize URI for signature base string."""
364
365
def collect_parameters(
366
uri_query: str = "",
367
body: str | None = None,
368
headers: dict[str, str] | None = None,
369
exclude_oauth_signature: bool = True,
370
with_realm: bool = False,
371
) -> list[tuple[str, str]]:
372
"""Collect OAuth parameters for signature."""
373
374
def normalize_parameters(params: list[tuple[str, str]]) -> str:
375
"""Normalize parameters for signature base string."""
376
377
# HMAC signature methods
378
def sign_hmac_sha1(base_string: str, client_secret: str, resource_owner_secret: str) -> str:
379
"""Sign with HMAC-SHA1."""
380
381
def verify_hmac_sha1(
382
request,
383
client_secret: str = None,
384
resource_owner_secret: str = None,
385
) -> bool:
386
"""Verify HMAC-SHA1 signature."""
387
388
def sign_hmac_sha256(base_string: str, client_secret: str, resource_owner_secret: str) -> str:
389
"""Sign with HMAC-SHA256."""
390
391
def verify_hmac_sha256(
392
request,
393
client_secret: str = None,
394
resource_owner_secret: str = None,
395
) -> bool:
396
"""Verify HMAC-SHA256 signature."""
397
398
def sign_hmac_sha512(base_string: str, client_secret: str, resource_owner_secret: str) -> str:
399
"""Sign with HMAC-SHA512."""
400
401
def verify_hmac_sha512(
402
request,
403
client_secret: str = None,
404
resource_owner_secret: str = None,
405
) -> bool:
406
"""Verify HMAC-SHA512 signature."""
407
408
# RSA signature methods
409
def sign_rsa_sha1(base_string: str, rsa_private_key: str) -> str:
410
"""Sign with RSA-SHA1."""
411
412
def verify_rsa_sha1(request, rsa_public_key: str) -> bool:
413
"""Verify RSA-SHA1 signature."""
414
415
def sign_rsa_sha256(base_string: str, rsa_private_key: str) -> str:
416
"""Sign with RSA-SHA256."""
417
418
def verify_rsa_sha256(request, rsa_public_key: str) -> bool:
419
"""Verify RSA-SHA256 signature."""
420
421
def sign_rsa_sha512(base_string: str, rsa_private_key: str) -> str:
422
"""Sign with RSA-SHA512."""
423
424
def verify_rsa_sha512(request, rsa_public_key: str) -> bool:
425
"""Verify RSA-SHA512 signature."""
426
427
# Plaintext signature method
428
def sign_plaintext(client_secret: str, resource_owner_secret: str) -> str:
429
"""Sign with PLAINTEXT method."""
430
431
def verify_plaintext(
432
request,
433
client_secret: str = None,
434
resource_owner_secret: str = None,
435
) -> bool:
436
"""Verify PLAINTEXT signature."""
437
```
438
439
### Parameter Utilities
440
441
OAuth 1.0 parameter formatting and preparation utilities for different signature placement methods.
442
443
```python { .api }
444
def prepare_headers(
445
params: list[tuple[str, str]],
446
headers: dict[str, str] | None = None,
447
realm: str | None = None,
448
) -> dict[str, str]:
449
"""Prepare OAuth parameters for Authorization header."""
450
451
def prepare_form_encoded_body(
452
oauth_params: list[tuple[str, str]],
453
body: str | list[tuple[str, str]],
454
) -> str:
455
"""Prepare OAuth parameters for form-encoded body."""
456
457
def prepare_request_uri_query(
458
oauth_params: list[tuple[str, str]],
459
uri: str,
460
) -> str:
461
"""Prepare OAuth parameters for URI query string."""
462
```
463
464
### Utility Functions
465
466
OAuth 1.0 utility functions for parameter handling, URL encoding, and header parsing.
467
468
```python { .api }
469
def filter_oauth_params(params: list[tuple[str, str]]) -> list[str]:
470
"""Filter OAuth-specific parameters."""
471
472
def escape(u: str) -> str:
473
"""URL escape string for OAuth."""
474
475
def unescape(u: str) -> str:
476
"""URL unescape string."""
477
478
def parse_authorization_header(authorization_header: str) -> list[tuple[str, str]]:
479
"""Parse OAuth Authorization header."""
480
481
def parse_http_list(u: str) -> list[str]:
482
"""Parse HTTP list format."""
483
484
def parse_keqv_list(l: list[str]) -> dict[str, str]:
485
"""Parse key=value list format."""
486
487
def filter_params(target: list[str]) -> callable:
488
"""Create parameter filter function."""
489
```
490
491
## Constants
492
493
```python { .api }
494
# Signature methods
495
SIGNATURE_HMAC_SHA1: str
496
SIGNATURE_HMAC_SHA256: str
497
SIGNATURE_HMAC_SHA512: str
498
SIGNATURE_HMAC: str
499
SIGNATURE_RSA_SHA1: str
500
SIGNATURE_RSA_SHA256: str
501
SIGNATURE_RSA_SHA512: str
502
SIGNATURE_RSA: str
503
SIGNATURE_PLAINTEXT: str
504
505
# Signature placement
506
SIGNATURE_TYPE_AUTH_HEADER: str
507
SIGNATURE_TYPE_QUERY: str
508
SIGNATURE_TYPE_BODY: str
509
510
# Content type
511
CONTENT_TYPE_FORM_URLENCODED: str
512
```
513
514
## Exceptions
515
516
```python { .api }
517
class OAuth1Error(Exception):
518
"""Base OAuth 1.0 exception."""
519
error: str
520
description: str
521
uri: str | None
522
status_code: int
523
524
def __init__(
525
self,
526
description: str | None = None,
527
uri: str | None = None,
528
status_code: int = 400,
529
request=None,
530
) -> None: ...
531
532
def in_uri(self, uri: str) -> str: ...
533
534
@property
535
def twotuples(self) -> list[tuple[str, str]]: ...
536
537
@property
538
def urlencoded(self) -> str: ...
539
540
class InsecureTransportError(OAuth1Error):
541
"""HTTPS transport required."""
542
error: str
543
description: str
544
545
class InvalidSignatureMethodError(OAuth1Error):
546
"""Invalid signature method."""
547
error: str
548
549
class InvalidRequestError(OAuth1Error):
550
"""Invalid OAuth request."""
551
error: str
552
553
class InvalidClientError(OAuth1Error):
554
"""Invalid client credentials."""
555
error: str
556
```