PYTHON

Implementing OAuth 2.0 Client Credentials Flow in Python for Server-to-Server Auth

Securely obtain an access token using the OAuth 2.0 Client Credentials grant type in Python, ideal for server-to-server API integrations without user involvement.

import requests
import os

# Load environment variables for sensitive data
# pip install python-dotenv and create a .env file:
# CLIENT_ID=your_client_id
# CLIENT_SECRET=your_client_secret
# TOKEN_URL=https://your-oauth-server.com/oauth/token

from dotenv import load_dotenv
load_dotenv()

# Configuration from environment variables
CLIENT_ID = os.getenv('CLIENT_ID')
CLIENT_SECRET = os.getenv('CLIENT_SECRET')
TOKEN_URL = os.getenv('TOKEN_URL')

def get_oauth_token():
    """Obtains an OAuth 2.0 access token using the Client Credentials flow."""
    if not all([CLIENT_ID, CLIENT_SECRET, TOKEN_URL]):
        raise ValueError("Missing one or more OAuth configuration environment variables.")

    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    payload = {
        'grant_type': 'client_credentials',
        'client_id': CLIENT_ID,
        'client_secret': CLIENT_SECRET
    }

    try:
        print(f"Requesting token from: {TOKEN_URL}")
        response = requests.post(TOKEN_URL, headers=headers, data=payload)
        response.raise_for_status()  # Raise an exception for HTTP errors (4xx or 5xx)
        
        token_data = response.json()
        access_token = token_data.get('access_token')
        expires_in = token_data.get('expires_in')
        token_type = token_data.get('token_type')

        if not access_token:
            raise ValueError("Access token not found in response.")

        print("Successfully obtained access token.")
        print(f"Token Type: {token_type}, Expires In: {expires_in} seconds")
        return access_token

    except requests.exceptions.HTTPError as err:
        print(f"HTTP Error: {err}")
        print(f"Response: {err.response.text}")
        return None
    except requests.exceptions.RequestException as err:
        print(f"Request Error: {err}")
        return None
    except ValueError as err:
        print(f"Data Error: {err}")
        return None

def call_protected_api(access_token, api_url):
    """Calls a protected API using the obtained access token."""
    if not access_token:
        print("No access token provided. Cannot call protected API.")
        return None
    
    headers = {
        'Authorization': f'Bearer {access_token}',
        'Content-Type': 'application/json'
    }

    try:
        print(f"Calling protected API: {api_url}")
        response = requests.get(api_url, headers=headers)
        response.raise_for_status()
        print("Protected API response:")
        return response.json()
    except requests.exceptions.HTTPError as err:
        print(f"HTTP Error calling protected API: {err}")
        print(f"Response: {err.response.text}")
        return None
    except requests.exceptions.RequestException as err:
        print(f"Request Error calling protected API: {err}")
        return None

# --- Example Usage ---
if __name__ == "__main__":
    # Make sure your .env file has CLIENT_ID, CLIENT_SECRET, and TOKEN_URL
    # For a real API, replace 'https://api.example.com/data' with your protected endpoint
    PROTECTED_API_URL = 'https://api.example.com/data'

    token = get_oauth_token()
    if token:
        print(f"Access Token: {token[:20]}...") # Print a snippet for security
        api_response = call_protected_api(token, PROTECTED_API_URL)
        if api_response:
            print(api_response)
    else:
        print("Failed to obtain OAuth token.")
How it works: This Python snippet demonstrates how to implement the OAuth 2.0 Client Credentials grant type, a secure method for server-to-server API authentication where no user interaction is required. It uses the `requests` library to send a POST request to an OAuth token endpoint, including the `client_id` and `client_secret` to obtain an `access_token`. Once the token is acquired, it's used in the `Authorization` header as a Bearer token for subsequent requests to protected API resources. This flow is critical for applications that need to access API resources on their own behalf, rather than on behalf of a user.

Need help integrating this into your project?

Our team of expert developers can help you build your custom application from scratch.

Hire DigitalCodeLabs