OAuth v1.0 authentication hook for the Python requests HTTP library
npx @tessl/cli install tessl/pypi-requests-oauth@0.4.0OAuth 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.
pip install requests-oauthfrom oauth_hook import OAuthHookAlternative imports:
from oauth_hook.hook import OAuthHook
from oauth_hook.auth import Consumer, Token, SignatureMethod_HMAC_SHA1
from oauth_hook.hook import CustomSignatureMethod_HMAC_SHA1from oauth_hook import OAuthHook
import requests
# Initialize with access token and consumer credentials
oauth_hook = OAuthHook(
access_token="your_access_token",
access_token_secret="your_access_token_secret",
consumer_key="your_consumer_key",
consumer_secret="your_consumer_secret",
header_auth=True # Use Authorization header (preferred)
)
# Attach hook to requests session
client = requests.session(hooks={'pre_request': oauth_hook})
# Make authenticated requests
response = client.get('https://api.twitter.com/1/account/rate_limit_status.json')
response = client.post('https://api.twitter.com/1/statuses/update.json',
{'status': 'Hello OAuth!'})Class-level configuration for reuse:
# Set consumer credentials once
OAuthHook.consumer_key = "your_consumer_key"
OAuthHook.consumer_secret = "your_consumer_secret"
# Initialize with only token parameters
oauth_hook = OAuthHook("access_token", "access_token_secret", header_auth=True)Creates OAuth authentication hooks for signing HTTP requests.
class OAuthHook:
def __init__(
self,
access_token: str = None,
access_token_secret: str = None,
consumer_key: str = None,
consumer_secret: str = None,
header_auth: bool = None
):
"""
Initialize OAuth hook with credentials and authentication method.
Parameters:
- access_token: OAuth access token (optional for 3-legged auth flow)
- access_token_secret: OAuth access token secret (optional for 3-legged auth flow)
- consumer_key: OAuth consumer key (uses class attribute if None)
- consumer_secret: OAuth consumer secret (uses class attribute if None)
- header_auth: Use Authorization header if True, URL encoding if False
"""Signs HTTP requests with OAuth authentication parameters.
def __call__(self, request) -> requests.Request:
"""
Pre-request hook that signs a requests.Request for OAuth authentication.
Parameters:
- request: requests.Request object to be signed
Returns:
Modified requests.Request with OAuth authentication
"""Support for the complete OAuth authorization flow including request token acquisition, user authorization, and access token retrieval.
# Step 1: Request token acquisition
oauth_hook = OAuthHook(consumer_key="key", consumer_secret="secret")
client = requests.session(hooks={'pre_request': oauth_hook})
response = client.post('https://api.service.com/oauth/request_token',
data={'oauth_callback': 'oob'})
# Step 2: User authorization (redirect user to authorization URL)
# User provides verifier/PIN after authorization
# Step 3: Access token exchange
oauth_hook = OAuthHook(request_token, request_token_secret,
consumer_key, consumer_secret)
response = client.post('https://api.service.com/oauth/access_token',
{'oauth_verifier': verifier})Static methods for URL and parameter processing during OAuth signing.
@staticmethod
def get_normalized_url(url: str) -> str:
"""
Returns a normalized URL without query parameters, ports, or fragments.
Parameters:
- url: URL to normalize
Returns:
Normalized URL string
Raises:
ValueError: For unsupported URL schemes (non-HTTP/HTTPS)
"""
@staticmethod
def get_normalized_parameters(request) -> str:
"""
Returns URL-encoded parameter string for OAuth signature generation.
Parameters:
- request: requests.Request object
Returns:
URL-encoded parameter string for signing
"""
@staticmethod
def to_url(request) -> str:
"""
Serialize request as URL with OAuth parameters for GET requests.
Parameters:
- request: requests.Request object
Returns:
Complete URL with OAuth parameters
"""
@staticmethod
def to_postdata(request) -> str:
"""
Serialize request as POST data with OAuth parameters.
Parameters:
- request: requests.Request object
Returns:
URL-encoded POST data string
"""
@staticmethod
def authorization_header(oauth_params: dict) -> str:
"""
Generate OAuth Authorization header from parameters.
Parameters:
- oauth_params: Dictionary of OAuth parameters
Returns:
OAuth Authorization header string
"""
@staticmethod
def _split_url_string(query_string: str) -> dict:
"""
Parse query string into dictionary with unquoted values.
Parameters:
- query_string: URL query string to parse
Returns:
Dictionary with unquoted parameter values
"""Global configuration options for OAuth authentication.
# Class attributes for global configuration
OAuthHook.consumer_key = None # Global consumer key
OAuthHook.consumer_secret = None # Global consumer secret
OAuthHook.header_auth = False # Default authentication method
OAuthHook.OAUTH_VERSION = '1.0' # OAuth version
OAuthHook.signature = CustomSignatureMethod_HMAC_SHA1() # Signature method instanceUses the Authorization header with OAuth parameters. This is the preferred method following RFC 5849 and supported by services like Twitter.
oauth_hook = OAuthHook(
access_token, access_token_secret,
consumer_key, consumer_secret,
header_auth=True
)Embeds OAuth parameters in the URL query string or POST body. This is the default method and more widely supported across different services.
oauth_hook = OAuthHook(
access_token, access_token_secret,
consumer_key, consumer_secret,
header_auth=False # Default
)class Consumer:
"""OAuth consumer representation."""
def __init__(self, key: str, secret: str):
"""
Initialize consumer with key and secret.
Parameters:
- key: Consumer key
- secret: Consumer secret
"""
self.key: str
self.secret: str
class Token:
"""OAuth token representation."""
def __init__(self, key: str, secret: str):
"""
Initialize token with key and secret.
Parameters:
- key: Token key
- secret: Token secret
"""
self.key: str
self.secret: str
class SignatureMethod_HMAC_SHA1:
"""HMAC-SHA1 signature method for OAuth."""
name: str = 'HMAC-SHA1'
def sign(self, request, consumer: Consumer, token: Token) -> str:
"""
Generate OAuth signature for request.
Parameters:
- request: Request object to sign
- consumer: OAuth consumer
- token: OAuth token
Returns:
Base64-encoded HMAC-SHA1 signature
"""
def check(self, request, consumer: Consumer, token: Token, signature: str) -> bool:
"""
Verify OAuth signature.
Parameters:
- request: Request object
- consumer: OAuth consumer
- token: OAuth token
- signature: Signature to verify
Returns:
True if signature is valid
"""
def signing_base(self, request, consumer: Consumer, token: Token):
"""
Generate the signing base for OAuth signature.
Parameters:
- request: Request object to sign
- consumer: OAuth consumer
- token: OAuth token
Returns:
Tuple of (key, raw) for signature generation
"""
class CustomSignatureMethod_HMAC_SHA1(SignatureMethod_HMAC_SHA1):
"""
Custom HMAC-SHA1 signature method that extends the base implementation
with OAuth-specific signing base generation.
"""
def signing_base(self, request, consumer: Consumer, token: Token) -> tuple:
"""
Generate the OAuth signature base string and signing key.
This method creates the signature base string according to OAuth 1.0
specification, combining HTTP method, normalized URL, and normalized parameters.
Parameters:
- request: Request object containing method, URL, and parameters
- consumer: OAuth consumer with secret for signing
- token: OAuth token with secret for signing (optional)
Returns:
Tuple of (signing_key, base_string) for HMAC-SHA1 signature generation
"""def to_utf8(x):
"""
Convert input to UTF-8 encoding.
Parameters:
- x: String, unicode, or iterable containing strings
Returns:
UTF-8 encoded string or list of UTF-8 encoded strings
"""
def escape(url: str) -> str:
"""
URL escape string with safe='~' for OAuth parameter encoding.
Parameters:
- url: String to escape
Returns:
URL-escaped string
"""
def generate_verifier(length: int = 8) -> str:
"""
Generate random numeric verifier string for OAuth.
Parameters:
- length: Length of verifier (default: 8)
Returns:
Random numeric string
"""The package raises the following exceptions:
get_normalized_url()