requests-auth
requests-auth provides a collection of authentication classes that extend the capabilities of the popular Python `requests` library. It simplifies the implementation of various authentication schemes like OAuth2 (Authorization Code, Client Credentials, PKCE), Okta, Microsoft Entra ID (formerly Azure Active Directory), API Key, Basic, and NTLM. The current version is 8.0.0, released on June 18, 2024, and it typically follows the release cadence of its underlying `requests` and `requests-oauthlib` dependencies, with new features and bug fixes released as needed.
Common errors
-
ModuleNotFoundError: No module named 'requests_auth'
cause `requests-auth` library is not installed or the Python environment where it was installed is not the one being used to run the script.fixEnsure the library is installed in the active Python environment: `pip install requests-auth`. -
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: ...
cause The provided authentication credentials (API key, OAuth token, client ID/secret, username/password) are incorrect, expired, or lack the necessary permissions for the requested resource.fixVerify that your credentials are correct, up-to-date, and have the necessary scopes/permissions. Double-check for typos, leading/trailing spaces, or improper encoding. Consult the API documentation for correct authentication methods and required parameters. -
requests.exceptions.HTTPError: 400 Bad Request: {'error': 'invalid_grant', 'error_description': '...'}cause Common in OAuth2 flows when the authorization code or refresh token is invalid, expired, revoked, or does not match the redirection URI/client for which it was issued. This can also occur if the client secret is incorrect or if the server clock is out of sync.fixFor Authorization Code flow, ensure the `redirect_uri` in the initial authorization request exactly matches the one used to exchange the code for a token. Verify the client ID and secret. Ensure that the authorization code hasn't been used multiple times or expired. Check server time synchronization. If using refresh tokens, ensure they are valid and not expired/revoked.
Warnings
- gotcha When using OAuth2 flows (e.g., Authorization Code), requests-auth might attempt to open a web browser for user interaction. This can be problematic in headless environments or CI/CD pipelines. Refer to the library's documentation for headless options if available (e.g., `display_settings`).
- gotcha Directly passing username and password for basic authentication in a URL (e.g., `http://user:pass@example.com`) is generally not recommended as it can expose credentials in logs or browser history. While `requests` supports a tuple `auth=('user', 'pass')`, ensure sensitive information is handled securely.
- breaking No explicit breaking changes for `requests-auth` version 8.0.0 were found in its direct changelog or release notes. However, it relies heavily on the `requests` library. Upgrades to `requests` itself (e.g., 2.31.0+ fixed a Proxy-Authorization header forwarding vulnerability, and future versions might drop older Python support) could indirectly impact applications using `requests-auth`.
Install
-
pip install requests-auth
Imports
- OAuth2AuthorizationCode
from requests_auth import OAuth2AuthorizationCode
- OAuth2ClientCredentials
from requests_auth import OAuth2ClientCredentials
- ApiKeyAuth
from requests_auth import ApiKeyAuth
- BearerTokenAuth
from requests_auth.authentication import BearerTokenAuth
- OktaAuthorizationCode
from requests_auth import OktaAuthorizationCode
- MicrosoftAuthorizationCode
from requests_auth import MicrosoftAuthorizationCode
Quickstart
import requests
import os
from requests_auth import OAuth2ClientCredentials
# --- Client Credentials Flow Example ---
# Replace with your actual client_id, client_secret, token_url, and API endpoint
CLIENT_ID = os.environ.get('OAUTH_CLIENT_ID', 'your_client_id')
CLIENT_SECRET = os.environ.get('OAUTH_CLIENT_SECRET', 'your_client_secret')
TOKEN_URL = os.environ.get('OAUTH_TOKEN_URL', 'https://example.com/oauth/token')
API_ENDPOINT = os.environ.get('API_ENDPOINT', 'https://api.example.com/data')
if CLIENT_ID and CLIENT_SECRET and TOKEN_URL and API_ENDPOINT:
try:
# Initialize OAuth2ClientCredentials auth
auth = OAuth2ClientCredentials(
token_url=TOKEN_URL,
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET
)
# Make an authenticated request
response = requests.get(API_ENDPOINT, auth=auth)
response.raise_for_status() # Raise an exception for HTTP errors
print(f"Client Credentials API Response: {response.json()}")
except requests.exceptions.HTTPError as e:
print(f"Client Credentials HTTP Error: {e.response.status_code} - {e.response.text}")
except Exception as e:
print(f"An error occurred during Client Credentials flow: {e}")
else:
print("Skipping Client Credentials example: Environment variables for client ID, secret, token URL, or API endpoint are not set.")
# --- API Key in Header Example ---
# Replace with your actual API key and endpoint
API_KEY_HEADER = os.environ.get('API_KEY_HEADER', 'your_api_key_value')
API_KEY_HEADER_NAME = 'X-API-Key'
API_ENDPOINT_HEADER = os.environ.get('API_ENDPOINT_HEADER', 'https://api.example.com/header-data')
if API_KEY_HEADER and API_ENDPOINT_HEADER:
try:
# Initialize ApiKeyAuth for header
auth_header = ApiKeyAuth(
API_KEY_HEADER,
API_KEY_HEADER_NAME,
'header'
)
response_header = requests.get(API_ENDPOINT_HEADER, auth=auth_header)
response_header.raise_for_status()
print(f"API Key (Header) API Response: {response_header.json()}")
except requests.exceptions.HTTPError as e:
print(f"API Key (Header) HTTP Error: {e.response.status_code} - {e.response.text}")
except Exception as e:
print(f"An error occurred during API Key (Header) example: {e}")
else:
print("Skipping API Key (Header) example: Environment variables for API key or endpoint are not set.")
# --- Bearer Token Auth Example (using a pre-obtained token) ---
# In a real application, this token would typically come from an OAuth2 flow.
BEARER_TOKEN = os.environ.get('BEARER_TOKEN', 'your_bearer_token')
API_ENDPOINT_BEARER = os.environ.get('API_ENDPOINT_BEARER', 'https://api.example.com/bearer-data')
if BEARER_TOKEN and API_ENDPOINT_BEARER:
try:
# Initialize BearerTokenAuth
bearer_auth = BearerTokenAuth(BEARER_TOKEN)
response_bearer = requests.get(API_ENDPOINT_BEARER, auth=bearer_auth)
response_bearer.raise_for_status()
print(f"Bearer Token API Response: {response_bearer.json()}")
except requests.exceptions.HTTPError as e:
print(f"Bearer Token HTTP Error: {e.response.status_code} - {e.response.text}")
except Exception as e:
print(f"An error occurred during Bearer Token example: {e}")
else:
print("Skipping Bearer Token example: Environment variables for bearer token or endpoint are not set.")