{"id":306,"library":"requests-oauthlib","title":"Requests-OAuthlib","description":"Requests-OAuthlib provides first-class OAuth 1.0 and OAuth 2.0 authentication support for the popular Python Requests HTTP library. It leverages the OAuthlib framework to offer an easy-to-use interface for building OAuth clients, simplifying the complexities of OAuth workflows. The library is actively maintained, with a typical release cadence driven by updates to the underlying OAuthlib library and security best practices.","status":"active","version":"2.0.0","language":"python","source_language":"en","source_url":"https://github.com/requests/requests-oauthlib","tags":["oauth","oauth1","oauth2","requests","authentication","security"],"install":[{"cmd":"pip install requests requests-oauthlib","lang":"bash","label":"Install stable version"}],"dependencies":[{"reason":"Core HTTP library for making requests.","package":"requests"},{"reason":"Underlying OAuth protocol implementation; requests-oauthlib is a wrapper around it.","package":"oauthlib"}],"imports":[{"symbol":"OAuth1Session","correct":"from requests_oauthlib import OAuth1Session"},{"symbol":"OAuth2Session","correct":"from requests_oauthlib import OAuth2Session"}],"quickstart":{"code":"import os\nfrom requests_oauthlib import OAuth2Session\n\n# Replace with your actual client ID and secret from your OAuth provider\nCLIENT_ID = os.environ.get('OAUTH_CLIENT_ID', 'your_client_id')\nCLIENT_SECRET = os.environ.get('OAUTH_CLIENT_SECRET', 'your_client_secret')\n\n# These URLs are specific to your OAuth provider (e.g., GitHub, Google)\nAUTHORIZATION_BASE_URL = 'https://github.com/login/oauth/authorize'\nTOKEN_URL = 'https://github.com/login/oauth/access_token'\nREDIRECT_URI = 'http://localhost:5000/callback'\nSCOPE = ['user'] # Example scope for GitHub\n\ndef get_authorization_url():\n    \"\"\"Step 1: Get the authorization URL to redirect the user.\"\"\"\n    github = OAuth2Session(CLIENT_ID, redirect_uri=REDIRECT_URI, scope=SCOPE)\n    authorization_url, state = github.authorization_url(AUTHORIZATION_BASE_URL)\n    print(f\"Please go to {authorization_url} and authorize access.\")\n    print(f\"Store this state parameter for callback validation: {state}\")\n    return authorization_url, state\n\ndef fetch_token_from_callback(authorization_response_url, stored_state):\n    \"\"\"Step 2 & 3: Exchange the authorization code for an access token.\n       In a real web app, authorization_response_url comes from the redirect callback.\n    \"\"\"\n    github = OAuth2Session(CLIENT_ID, state=stored_state, redirect_uri=REDIRECT_URI)\n    try:\n        token = github.fetch_token(TOKEN_URL,\n                                   client_secret=CLIENT_SECRET,\n                                   authorization_response=authorization_response_url)\n        print(f\"Access Token obtained: {token}\")\n        # Now you can use the 'github' session to make API calls\n        user_info = github.get('https://api.github.com/user').json()\n        print(f\"Authenticated user info: {user_info}\")\n        return token, user_info\n    except Exception as e:\n        print(f\"Error fetching token: {e}\")\n        return None, None\n\nif __name__ == \"__main__\":\n    auth_url, initial_state = get_authorization_url()\n    # In a real application, you would redirect the user to auth_url\n    # and then capture the full redirect URL (authorization_response_url)\n    # from their browser after they authorize your application.\n    print(\"\\n--- Manual Step Required ---\")\n    print(\"1. Open the URL printed above in your browser.\")\n    print(\"2. Authorize the application.\")\n    print(\"3. After authorization, copy the full URL from your browser's address bar.\")\n    print(\"   (It will likely be http://localhost:5000/callback?code=...&state=...)\")\n    authorization_response = input(\"\\nEnter the full redirect URL here: \")\n\n    # Simulate callback handling\n    if authorization_response:\n        fetch_token_from_callback(authorization_response, initial_state)\n    else:\n        print(\"No authorization response provided. Exiting.\")","lang":"python","description":"Demonstrates the OAuth 2.0 Authorization Code Grant flow using `OAuth2Session` to obtain an access token. This example simulates a web application flow, where the user is manually prompted to visit the authorization URL and paste the resulting redirect URL. In a real application, this would involve a web framework (like Flask or Django) handling the redirects automatically. Remember to set `OAUTH_CLIENT_ID` and `OAUTH_CLIENT_SECRET` as environment variables or replace placeholders."},"warnings":[{"fix":"Upgrade Python to 3.7+ or use requests-oauthlib version 1.x.x.","message":"Version 2.0.0 dropped support for Python 2.x and Python versions older than 3.7. Users on older Python versions must remain on requests-oauthlib < 2.0.0 or upgrade their Python environment.","severity":"breaking","affected_versions":"<2.0.0"},{"fix":"Ensure all OAuth 2.0 endpoints (authorization_base_url, token_url, etc.) use `https://`. For local testing, set the environment variable `OAUTHLIB_INSECURE_TRANSPORT='1'` (never in production).","message":"Requests-oauthlib 2.0.0 (and its underlying dependency oauthlib 3.x.x) strictly enforces HTTPS for all OAuth 2.0 authorization endpoints. Attempting to use HTTP will raise an `InsecureTransportError`.","severity":"breaking","affected_versions":"2.0.0+"},{"fix":"Adopt the Authorization Code Grant flow, preferably with PKCE, for new implementations and migrate existing flows away from Implicit and ROPC grants.","message":"The Implicit Grant and Resource Owner Password Credentials (ROPC) flows are considered insecure and are formally deprecated in OAuth 2.1. While requests-oauthlib might still support them for OAuth 2.0, it's strongly recommended to migrate to the Authorization Code Flow, especially with PKCE for public clients (SPAs, mobile apps).","severity":"deprecated","affected_versions":"All OAuth 2.0 usage"},{"fix":"Always register and use exact, specific `redirect_uri` values with your OAuth provider. Avoid patterns or wildcards in production environments.","message":"OAuth 2.1 (which modern implementations aim for) requires exact matching of `redirect_uri`. Using wildcard or partial matching for `redirect_uri` can lead to open redirect vulnerabilities.","severity":"gotcha","affected_versions":"All OAuth 2.0 usage"},{"fix":"Ensure your OAuth provider's token response includes an accurate `expires_in` parameter. If not, implement custom logic to manage token expiration and refreshing.","message":"Properly managing `expires_in` for access tokens is crucial for automatic token refreshing. If `expires_in` is not accurately provided by the OAuth provider, requests-oauthlib cannot reliably determine token expiration, impacting refresh logic.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T12:58:33.101Z","next_check":"2026-07-11T00:00:00.000Z","problems":[],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":0,"quickstart_tag":"stale","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.68,"mem_mb":11.3,"disk_size":"22.8M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.48,"mem_mb":11.3,"disk_size":"23M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.85,"mem_mb":12.7,"disk_size":"25.0M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.69,"mem_mb":12.7,"disk_size":"25M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.77,"mem_mb":12.5,"disk_size":"16.7M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.74,"mem_mb":12.5,"disk_size":"17M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.72,"mem_mb":12.8,"disk_size":"16.4M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.73,"mem_mb":12.8,"disk_size":"17M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.59,"mem_mb":11.1,"disk_size":"22.1M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.54,"mem_mb":11.1,"disk_size":"23M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"stale","tag_description":"widespread failures or data too old to trust","results":[{"runtime":"python:3.10-alpine","exit_code":1},{"runtime":"python:3.10-slim","exit_code":1},{"runtime":"python:3.11-alpine","exit_code":1},{"runtime":"python:3.11-slim","exit_code":1},{"runtime":"python:3.12-alpine","exit_code":1},{"runtime":"python:3.12-slim","exit_code":1},{"runtime":"python:3.13-alpine","exit_code":1},{"runtime":"python:3.13-slim","exit_code":1},{"runtime":"python:3.9-alpine","exit_code":1},{"runtime":"python:3.9-slim","exit_code":1}]}}