0
# OAuth 1.0a Implementation
1
2
OAuth 1.0a authentication support with complete workflow management, request signing, and token handling. Supports all signature methods and provides both low-level authentication and high-level session-based workflows.
3
4
## Capabilities
5
6
### OAuth1 Authentication Class
7
8
Low-level authentication handler that signs individual requests using OAuth 1.0a protocol. Implements the `requests.auth.AuthBase` interface for seamless integration with existing request code.
9
10
```python { .api }
11
class OAuth1(requests.auth.AuthBase):
12
def __init__(
13
self,
14
client_key: str,
15
client_secret: str = None,
16
resource_owner_key: str = None,
17
resource_owner_secret: str = None,
18
callback_uri: str = None,
19
signature_method: str = SIGNATURE_HMAC,
20
signature_type: str = SIGNATURE_TYPE_AUTH_HEADER,
21
rsa_key: str = None,
22
verifier: str = None,
23
decoding: str = "utf-8",
24
client_class = None,
25
force_include_body: bool = False,
26
**kwargs
27
):
28
"""
29
Create OAuth 1.0a authentication handler.
30
31
Args:
32
client_key (str): Client identifier from OAuth provider
33
client_secret (str, optional): Client secret for HMAC/plaintext signatures
34
resource_owner_key (str, optional): Request token or access token
35
resource_owner_secret (str, optional): Token secret from provider
36
callback_uri (str, optional): Callback URL for authorization
37
signature_method (str): Signature method (SIGNATURE_HMAC, SIGNATURE_RSA, SIGNATURE_PLAIN)
38
signature_type (str): Parameter placement (SIGNATURE_TYPE_AUTH_HEADER, SIGNATURE_TYPE_QUERY, SIGNATURE_TYPE_BODY)
39
rsa_key (str, optional): RSA private key for RSA-SHA1 signing
40
verifier (str, optional): Verifier from authorization step
41
decoding (str): Character encoding (default: "utf-8")
42
client_class: Custom oauthlib.oauth1.Client subclass
43
force_include_body (bool): Include request body in non-form requests
44
"""
45
```
46
47
**Usage Example:**
48
49
```python
50
import requests
51
from requests_oauthlib import OAuth1
52
53
# Create auth handler
54
auth = OAuth1(
55
'client_key',
56
client_secret='client_secret',
57
resource_owner_key='access_token',
58
resource_owner_secret='token_secret'
59
)
60
61
# Use with requests
62
response = requests.get('https://api.example.com/protected', auth=auth)
63
```
64
65
### OAuth1Session Workflow Class
66
67
High-level session class that extends `requests.Session` with OAuth 1.0a workflow methods. Handles the complete three-legged OAuth dance including request token fetching, authorization, and access token exchange.
68
69
```python { .api }
70
class OAuth1Session(requests.Session):
71
def __init__(
72
self,
73
client_key: str,
74
client_secret: str = None,
75
resource_owner_key: str = None,
76
resource_owner_secret: str = None,
77
callback_uri: str = None,
78
signature_method: str = SIGNATURE_HMAC,
79
signature_type: str = SIGNATURE_TYPE_AUTH_HEADER,
80
rsa_key: str = None,
81
verifier: str = None,
82
client_class = None,
83
force_include_body: bool = False,
84
**kwargs
85
):
86
"""
87
Create OAuth 1.0a session for complete workflow management.
88
89
Args:
90
client_key (str): Client identifier from OAuth provider
91
client_secret (str, optional): Client secret
92
resource_owner_key (str, optional): Request token or access token
93
resource_owner_secret (str, optional): Token secret
94
callback_uri (str, optional): Callback URL for authorization
95
signature_method (str): Signature method
96
signature_type (str): Parameter placement method
97
rsa_key (str, optional): RSA private key for RSA-SHA1
98
verifier (str, optional): Authorization verifier
99
client_class: Custom client class
100
force_include_body (bool): Include body in signature
101
"""
102
```
103
104
**Properties:**
105
106
```python { .api }
107
@property
108
def token(self) -> dict:
109
"""Token dictionary with oauth_token, oauth_token_secret, oauth_verifier"""
110
111
@token.setter
112
def token(self, value: dict):
113
"""Set token from dictionary"""
114
115
@property
116
def authorized(self) -> bool:
117
"""True if session has valid OAuth credentials"""
118
```
119
120
**Methods:**
121
122
```python { .api }
123
def authorization_url(
124
self,
125
url: str,
126
request_token: str = None,
127
**kwargs
128
) -> str:
129
"""
130
Create authorization URL for user consent.
131
132
Args:
133
url (str): Authorization endpoint URL
134
request_token (str, optional): Request token to include
135
**kwargs: Additional parameters for URL
136
137
Returns:
138
str: Complete authorization URL
139
"""
140
141
def fetch_request_token(
142
self,
143
url: str,
144
realm: list = None,
145
**request_kwargs
146
) -> dict:
147
"""
148
Fetch request token from provider.
149
150
Args:
151
url (str): Request token endpoint URL
152
realm (list, optional): List of realms for access
153
**request_kwargs: Additional arguments for request
154
155
Returns:
156
dict: Token response with oauth_token and oauth_token_secret
157
158
Raises:
159
TokenRequestDenied: If request fails
160
TokenMissing: If response lacks required token
161
"""
162
163
def fetch_access_token(
164
self,
165
url: str,
166
verifier: str = None,
167
**request_kwargs
168
) -> dict:
169
"""
170
Fetch access token using authorization verifier.
171
172
Args:
173
url (str): Access token endpoint URL
174
verifier (str, optional): Authorization verifier
175
**request_kwargs: Additional arguments for request
176
177
Returns:
178
dict: Access token response
179
180
Raises:
181
VerifierMissing: If no verifier is set
182
TokenRequestDenied: If request fails
183
"""
184
185
def parse_authorization_response(self, url: str) -> dict:
186
"""
187
Extract parameters from authorization callback URL.
188
189
Args:
190
url (str): Full callback URL from provider
191
192
Returns:
193
dict: Parsed parameters including verifier
194
"""
195
196
def rebuild_auth(self, prepared_request, response):
197
"""
198
Handle redirects by stripping and rebuilding authentication.
199
200
When being redirected we should always strip Authorization header,
201
since nonce may not be reused as per OAuth spec.
202
203
Args:
204
prepared_request: The prepared request object
205
response: The response that triggered the redirect
206
"""
207
```
208
209
**Complete Workflow Example:**
210
211
```python
212
from requests_oauthlib import OAuth1Session
213
214
# Step 1: Create session
215
oauth = OAuth1Session(
216
'client_key',
217
client_secret='client_secret',
218
callback_uri='https://example.com/callback'
219
)
220
221
# Step 2: Fetch request token
222
request_token_url = 'https://api.provider.com/oauth/request_token'
223
token = oauth.fetch_request_token(request_token_url)
224
print(f"Request token: {token}")
225
226
# Step 3: Get authorization URL
227
authorization_url = 'https://api.provider.com/oauth/authorize'
228
auth_url = oauth.authorization_url(authorization_url)
229
print(f"Go to: {auth_url}")
230
231
# Step 4: Parse callback (after user authorization)
232
callback_url = input("Enter the full callback URL: ")
233
verifier_data = oauth.parse_authorization_response(callback_url)
234
235
# Step 5: Fetch access token
236
access_token_url = 'https://api.provider.com/oauth/access_token'
237
access_token = oauth.fetch_access_token(access_token_url)
238
print(f"Access token: {access_token}")
239
240
# Step 6: Make authenticated requests
241
response = oauth.get('https://api.provider.com/user')
242
print(response.json())
243
```
244
245
### Exception Classes
246
247
```python { .api }
248
class TokenRequestDenied(ValueError):
249
"""Raised when token request is denied by provider"""
250
def __init__(self, message: str, response):
251
"""
252
Args:
253
message (str): Error description
254
response: HTTP response object
255
"""
256
257
@property
258
def status_code(self) -> int:
259
"""HTTP status code from failed request"""
260
261
class TokenMissing(ValueError):
262
"""Raised when token is missing from provider response"""
263
def __init__(self, message: str, response):
264
"""
265
Args:
266
message (str): Error description
267
response: Response that lacks token
268
"""
269
270
class VerifierMissing(ValueError):
271
"""Raised when OAuth verifier is missing for access token request"""
272
```
273
274
### Utility Functions
275
276
```python { .api }
277
def urldecode(body: str) -> dict:
278
"""
279
Parse URL-encoded or JSON response to Python dictionary.
280
281
Args:
282
body (str): Response body to parse
283
284
Returns:
285
dict: Parsed parameters
286
"""
287
```
288
289
**Import:**
290
291
```python
292
from requests_oauthlib.oauth1_session import urldecode
293
```
294
295
## Signature Methods
296
297
The library supports all OAuth 1.0a signature methods:
298
299
- **SIGNATURE_HMAC** (default): HMAC-SHA1 signatures using client secret and token secret
300
- **SIGNATURE_RSA**: RSA-SHA1 signatures using RSA private key
301
- **SIGNATURE_PLAIN**: Plain text signatures (not recommended for production)
302
303
## Signature Types
304
305
OAuth parameters can be included in different parts of the request:
306
307
- **SIGNATURE_TYPE_AUTH_HEADER** (default): Parameters in Authorization header
308
- **SIGNATURE_TYPE_QUERY**: Parameters in URL query string
309
- **SIGNATURE_TYPE_BODY**: Parameters in request body (form-encoded requests only)
310
311
## Security Considerations
312
313
- Always use HTTPS endpoints in production
314
- Store client secrets and tokens securely
315
- Use appropriate signature methods (HMAC or RSA recommended)
316
- Implement proper token storage and renewal workflows
317
- Validate callback URLs to prevent authorization hijacking