0
# requests-oauth
1
2
OAuth v1.0 authentication hook for the Python requests HTTP library. This package provides both header-based and URL-encoded authentication methods for OAuth-protected APIs, with header authentication being the preferred approach following RFC 5849 specifications.
3
4
## Package Information
5
6
- **Package Name**: requests-oauth
7
- **Language**: Python
8
- **Installation**: `pip install requests-oauth`
9
10
## Core Imports
11
12
```python
13
from oauth_hook import OAuthHook
14
```
15
16
Alternative imports:
17
18
```python
19
from oauth_hook.hook import OAuthHook
20
from oauth_hook.auth import Consumer, Token, SignatureMethod_HMAC_SHA1
21
from oauth_hook.hook import CustomSignatureMethod_HMAC_SHA1
22
```
23
24
## Basic Usage
25
26
```python
27
from oauth_hook import OAuthHook
28
import requests
29
30
# Initialize with access token and consumer credentials
31
oauth_hook = OAuthHook(
32
access_token="your_access_token",
33
access_token_secret="your_access_token_secret",
34
consumer_key="your_consumer_key",
35
consumer_secret="your_consumer_secret",
36
header_auth=True # Use Authorization header (preferred)
37
)
38
39
# Attach hook to requests session
40
client = requests.session(hooks={'pre_request': oauth_hook})
41
42
# Make authenticated requests
43
response = client.get('https://api.twitter.com/1/account/rate_limit_status.json')
44
response = client.post('https://api.twitter.com/1/statuses/update.json',
45
{'status': 'Hello OAuth!'})
46
```
47
48
Class-level configuration for reuse:
49
50
```python
51
# Set consumer credentials once
52
OAuthHook.consumer_key = "your_consumer_key"
53
OAuthHook.consumer_secret = "your_consumer_secret"
54
55
# Initialize with only token parameters
56
oauth_hook = OAuthHook("access_token", "access_token_secret", header_auth=True)
57
```
58
59
## Capabilities
60
61
### OAuth Hook Creation
62
63
Creates OAuth authentication hooks for signing HTTP requests.
64
65
```python { .api }
66
class OAuthHook:
67
def __init__(
68
self,
69
access_token: str = None,
70
access_token_secret: str = None,
71
consumer_key: str = None,
72
consumer_secret: str = None,
73
header_auth: bool = None
74
):
75
"""
76
Initialize OAuth hook with credentials and authentication method.
77
78
Parameters:
79
- access_token: OAuth access token (optional for 3-legged auth flow)
80
- access_token_secret: OAuth access token secret (optional for 3-legged auth flow)
81
- consumer_key: OAuth consumer key (uses class attribute if None)
82
- consumer_secret: OAuth consumer secret (uses class attribute if None)
83
- header_auth: Use Authorization header if True, URL encoding if False
84
"""
85
```
86
87
### Request Signing
88
89
Signs HTTP requests with OAuth authentication parameters.
90
91
```python { .api }
92
def __call__(self, request) -> requests.Request:
93
"""
94
Pre-request hook that signs a requests.Request for OAuth authentication.
95
96
Parameters:
97
- request: requests.Request object to be signed
98
99
Returns:
100
Modified requests.Request with OAuth authentication
101
"""
102
```
103
104
### Three-Legged OAuth Flow
105
106
Support for the complete OAuth authorization flow including request token acquisition, user authorization, and access token retrieval.
107
108
```python
109
# Step 1: Request token acquisition
110
oauth_hook = OAuthHook(consumer_key="key", consumer_secret="secret")
111
client = requests.session(hooks={'pre_request': oauth_hook})
112
response = client.post('https://api.service.com/oauth/request_token',
113
data={'oauth_callback': 'oob'})
114
115
# Step 2: User authorization (redirect user to authorization URL)
116
# User provides verifier/PIN after authorization
117
118
# Step 3: Access token exchange
119
oauth_hook = OAuthHook(request_token, request_token_secret,
120
consumer_key, consumer_secret)
121
response = client.post('https://api.service.com/oauth/access_token',
122
{'oauth_verifier': verifier})
123
```
124
125
### URL Utilities
126
127
Static methods for URL and parameter processing during OAuth signing.
128
129
```python { .api }
130
@staticmethod
131
def get_normalized_url(url: str) -> str:
132
"""
133
Returns a normalized URL without query parameters, ports, or fragments.
134
135
Parameters:
136
- url: URL to normalize
137
138
Returns:
139
Normalized URL string
140
141
Raises:
142
ValueError: For unsupported URL schemes (non-HTTP/HTTPS)
143
"""
144
145
@staticmethod
146
def get_normalized_parameters(request) -> str:
147
"""
148
Returns URL-encoded parameter string for OAuth signature generation.
149
150
Parameters:
151
- request: requests.Request object
152
153
Returns:
154
URL-encoded parameter string for signing
155
"""
156
157
@staticmethod
158
def to_url(request) -> str:
159
"""
160
Serialize request as URL with OAuth parameters for GET requests.
161
162
Parameters:
163
- request: requests.Request object
164
165
Returns:
166
Complete URL with OAuth parameters
167
"""
168
169
@staticmethod
170
def to_postdata(request) -> str:
171
"""
172
Serialize request as POST data with OAuth parameters.
173
174
Parameters:
175
- request: requests.Request object
176
177
Returns:
178
URL-encoded POST data string
179
"""
180
181
@staticmethod
182
def authorization_header(oauth_params: dict) -> str:
183
"""
184
Generate OAuth Authorization header from parameters.
185
186
Parameters:
187
- oauth_params: Dictionary of OAuth parameters
188
189
Returns:
190
OAuth Authorization header string
191
"""
192
193
@staticmethod
194
def _split_url_string(query_string: str) -> dict:
195
"""
196
Parse query string into dictionary with unquoted values.
197
198
Parameters:
199
- query_string: URL query string to parse
200
201
Returns:
202
Dictionary with unquoted parameter values
203
"""
204
```
205
206
### Class Attributes and Configuration
207
208
Global configuration options for OAuth authentication.
209
210
```python { .api }
211
# Class attributes for global configuration
212
OAuthHook.consumer_key = None # Global consumer key
213
OAuthHook.consumer_secret = None # Global consumer secret
214
OAuthHook.header_auth = False # Default authentication method
215
OAuthHook.OAUTH_VERSION = '1.0' # OAuth version
216
OAuthHook.signature = CustomSignatureMethod_HMAC_SHA1() # Signature method instance
217
```
218
219
## Authentication Methods
220
221
### Header Authentication (Recommended)
222
223
Uses the Authorization header with OAuth parameters. This is the preferred method following RFC 5849 and supported by services like Twitter.
224
225
```python
226
oauth_hook = OAuthHook(
227
access_token, access_token_secret,
228
consumer_key, consumer_secret,
229
header_auth=True
230
)
231
```
232
233
### URL-encoded Authentication
234
235
Embeds OAuth parameters in the URL query string or POST body. This is the default method and more widely supported across different services.
236
237
```python
238
oauth_hook = OAuthHook(
239
access_token, access_token_secret,
240
consumer_key, consumer_secret,
241
header_auth=False # Default
242
)
243
```
244
245
## Types
246
247
```python { .api }
248
class Consumer:
249
"""OAuth consumer representation."""
250
def __init__(self, key: str, secret: str):
251
"""
252
Initialize consumer with key and secret.
253
254
Parameters:
255
- key: Consumer key
256
- secret: Consumer secret
257
"""
258
self.key: str
259
self.secret: str
260
261
class Token:
262
"""OAuth token representation."""
263
def __init__(self, key: str, secret: str):
264
"""
265
Initialize token with key and secret.
266
267
Parameters:
268
- key: Token key
269
- secret: Token secret
270
"""
271
self.key: str
272
self.secret: str
273
274
class SignatureMethod_HMAC_SHA1:
275
"""HMAC-SHA1 signature method for OAuth."""
276
name: str = 'HMAC-SHA1'
277
278
def sign(self, request, consumer: Consumer, token: Token) -> str:
279
"""
280
Generate OAuth signature for request.
281
282
Parameters:
283
- request: Request object to sign
284
- consumer: OAuth consumer
285
- token: OAuth token
286
287
Returns:
288
Base64-encoded HMAC-SHA1 signature
289
"""
290
291
def check(self, request, consumer: Consumer, token: Token, signature: str) -> bool:
292
"""
293
Verify OAuth signature.
294
295
Parameters:
296
- request: Request object
297
- consumer: OAuth consumer
298
- token: OAuth token
299
- signature: Signature to verify
300
301
Returns:
302
True if signature is valid
303
"""
304
305
def signing_base(self, request, consumer: Consumer, token: Token):
306
"""
307
Generate the signing base for OAuth signature.
308
309
Parameters:
310
- request: Request object to sign
311
- consumer: OAuth consumer
312
- token: OAuth token
313
314
Returns:
315
Tuple of (key, raw) for signature generation
316
"""
317
318
class CustomSignatureMethod_HMAC_SHA1(SignatureMethod_HMAC_SHA1):
319
"""
320
Custom HMAC-SHA1 signature method that extends the base implementation
321
with OAuth-specific signing base generation.
322
"""
323
324
def signing_base(self, request, consumer: Consumer, token: Token) -> tuple:
325
"""
326
Generate the OAuth signature base string and signing key.
327
328
This method creates the signature base string according to OAuth 1.0
329
specification, combining HTTP method, normalized URL, and normalized parameters.
330
331
Parameters:
332
- request: Request object containing method, URL, and parameters
333
- consumer: OAuth consumer with secret for signing
334
- token: OAuth token with secret for signing (optional)
335
336
Returns:
337
Tuple of (signing_key, base_string) for HMAC-SHA1 signature generation
338
"""
339
```
340
341
## Utility Functions
342
343
```python { .api }
344
def to_utf8(x):
345
"""
346
Convert input to UTF-8 encoding.
347
348
Parameters:
349
- x: String, unicode, or iterable containing strings
350
351
Returns:
352
UTF-8 encoded string or list of UTF-8 encoded strings
353
"""
354
355
def escape(url: str) -> str:
356
"""
357
URL escape string with safe='~' for OAuth parameter encoding.
358
359
Parameters:
360
- url: String to escape
361
362
Returns:
363
URL-escaped string
364
"""
365
366
def generate_verifier(length: int = 8) -> str:
367
"""
368
Generate random numeric verifier string for OAuth.
369
370
Parameters:
371
- length: Length of verifier (default: 8)
372
373
Returns:
374
Random numeric string
375
"""
376
```
377
378
## Error Handling
379
380
The package raises the following exceptions:
381
382
- **ValueError**: Raised for unsupported URL schemes (non-HTTP/HTTPS) in `get_normalized_url()`
383
- **TypeError**: May be raised for invalid parameter types during request processing
384
385
## Dependencies
386
387
- **requests** >= 0.12.1: Python HTTP library for making requests
388
- **Standard library modules**: time, datetime, random, urllib, urlparse, binascii, hmac, hashlib/sha