CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-oauthlib

A comprehensive Python library for implementing OAuth 1.0 and OAuth 2.0 authentication protocols

Overview
Eval results
Files

oauth2-clients.mddocs/

OAuth 2.0 Clients

OAuth 2.0 client implementations supporting all standard grant types including authorization code, implicit, client credentials, and password flows. Includes PKCE support for enhanced security and specialized clients for different application architectures.

Capabilities

Base Client

Base OAuth 2.0 client providing core functionality for all grant types. Handles token management, request preparation, and response parsing with support for various token placement strategies.

class Client:
    def __init__(
        self,
        client_id: str,
        default_token_placement: str = "auth_header",
        token_type: str = "Bearer",
        access_token: str | None = None,
        refresh_token: str | None = None,
        mac_key: str | bytes | bytearray | None = None,
        mac_algorithm: str | None = None,
        token: dict[str, str] | None = None,
        scope: str | list[str] | None = None,
        state: str | None = None,
        redirect_url: str | None = None,
        state_generator: callable = ...,
        code_verifier: str | None = None,
        code_challenge: str | None = None,
        code_challenge_method: str | None = None,
        **kwargs,
    ):
        """
        Base OAuth 2.0 client.
        
        Parameters:
        - client_id: Client identifier
        - default_token_placement: Where to place access token (auth_header, query, body)
        - token_type: Token type (Bearer, MAC)
        - access_token: Current access token
        - refresh_token: Current refresh token
        - mac_key: MAC authentication key
        - mac_algorithm: MAC algorithm
        - token: Token dictionary
        - scope: Access scope
        - state: State parameter for CSRF protection
        - redirect_url: Redirect URL
        - state_generator: Function to generate state values
        - code_verifier: PKCE code verifier
        - code_challenge: PKCE code challenge
        - code_challenge_method: PKCE challenge method (plain, S256)
        """
    
    def add_token(
        self,
        uri: str,
        http_method: str = "GET",
        body: str | None = None,
        headers: dict[str, str] | None = None,
        token_placement: str | None = None,
        **kwargs,
    ) -> tuple[str, dict[str, str] | None, str | None]:
        """
        Add access token to request.
        
        Returns:
        Tuple of (uri, headers, body) with token applied
        """
    
    def prepare_authorization_request(
        self,
        authorization_url: str,
        state: str | None = None,
        redirect_url: str | None = None,
        scope: str | list[str] | None = None,
        **kwargs,
    ) -> tuple[str, dict[str, str], str]:
        """
        Prepare authorization request URL.
        
        Returns:
        Tuple of (url, headers, body) for authorization request
        """
    
    def prepare_token_request(
        self,
        token_url: str,
        authorization_response: str | None = None,
        redirect_url: str | None = None,
        state: str | None = None,
        body: str = "",
        **kwargs,
    ) -> tuple[str, dict[str, str], str]:
        """
        Prepare token request.
        
        Returns:
        Tuple of (url, headers, body) for token request
        """
    
    def prepare_refresh_token_request(
        self,
        token_url: str,
        refresh_token: str | None = None,
        body: str = "",
        scope: str | list[str] | None = None,
        **kwargs,
    ) -> tuple[str, dict[str, str], str]:
        """
        Prepare refresh token request.
        
        Returns:
        Tuple of (url, headers, body) for refresh request
        """
    
    def prepare_token_revocation_request(
        self,
        revocation_url: str,
        token: str,
        token_type_hint: str | None = "access_token",
        body: str = "",
        callback: callable | None = None,
        **kwargs,
    ) -> tuple[str, dict[str, str], str]:
        """
        Prepare token revocation request.
        
        Parameters:
        - revocation_url: Token revocation endpoint URL
        - token: Token to revoke
        - token_type_hint: Type of token (access_token, refresh_token)
        - body: Request body
        - callback: Callback function
        
        Returns:
        Tuple of (url, headers, body) for revocation request
        """
    
    def parse_request_body_response(
        self,
        body: str,
        scope: str | list[str] | None = None,
        **kwargs,
    ) -> dict[str, str]:
        """Parse token response body."""
    
    def parse_request_uri_response(self, *args, **kwargs) -> dict[str, str]:
        """Parse response from URI."""
    
    def prepare_refresh_body(
        self,
        body: str = "",
        refresh_token: str | None = None,
        scope: str | list[str] | None = None,
        **kwargs,
    ) -> str:
        """Prepare refresh token request body."""
    
    # PKCE methods
    def create_code_verifier(self, length: int) -> str:
        """Create PKCE code verifier."""
    
    def create_code_challenge(
        self,
        code_verifier: str,
        code_challenge_method: str | None = None,
    ) -> str:
        """Create PKCE code challenge."""
    
    # Token management
    def populate_code_attributes(self, response: dict[str, str]) -> None:
        """Populate authorization code attributes from response."""
    
    def populate_token_attributes(self, response: dict[str, str]) -> None:
        """Populate token attributes from response."""

Web Application Client

OAuth 2.0 client for web applications using the authorization code grant. Provides the most secure flow suitable for server-side applications that can securely store client credentials.

class WebApplicationClient(Client):
    def __init__(
        self,
        client_id: str,
        code: str | None = None,
        *,
        default_token_placement: str = "auth_header",
        token_type: str = "Bearer",
        access_token: str | None = None,
        refresh_token: str | None = None,
        mac_key: str | bytes | bytearray | None = None,
        mac_algorithm: str | None = None,
        token: dict[str, str] | None = None,
        scope: str | list[str] | None = None,
        state: str | None = None,
        redirect_url: str | None = None,
        state_generator: callable = ...,
        code_verifier: str | None = None,
        code_challenge: str | None = None,
        code_challenge_method: str | None = None,
        **kwargs,
    ):
        """
        Web application client for authorization code grant.
        
        Suitable for server-side applications that can securely store
        client credentials and handle redirect URIs.
        """
    
    def prepare_request_uri(
        self,
        uri: str,
        redirect_uri: str | None = None,
        scope: str | list[str] | None = None,
        state: str | None = None,
        code_challenge: str | None = None,
        code_challenge_method: str = "plain",
        **kwargs,
    ) -> str:
        """Prepare authorization request URI."""
    
    def prepare_request_body(
        self,
        code: str | None = None,
        redirect_uri: str | None = None,
        body: str = "",
        include_client_id: bool = True,
        code_verifier: str | None = None,
        *,
        scope: str | list[str] | None = None,
        client_id: str | None = None,
        client_secret: str | None = None,
        **kwargs,
    ) -> str:
        """Prepare token request body with authorization code."""
    
    def parse_request_uri_response(self, uri: str, state: str | None = None) -> dict[str, str]:
        """Parse authorization response from redirect URI."""

Usage example:

from oauthlib.oauth2 import WebApplicationClient
import requests

# Create client
client = WebApplicationClient('your-client-id')

# Step 1: Get authorization URL
auth_url = 'https://auth.example.com/authorize'
authorization_url, headers, body = client.prepare_authorization_request(
    auth_url,
    redirect_url='https://your-app.com/callback',
    scope=['read', 'write'],
    state='random-state-value'
)

# User visits authorization_url and gets redirected back with code

# Step 2: Exchange code for token
token_url = 'https://auth.example.com/token'
token_request_url, headers, body = client.prepare_token_request(
    token_url,
    authorization_response='https://your-app.com/callback?code=ABC123&state=random-state-value',
    redirect_url='https://your-app.com/callback'
)

# Make token request
response = requests.post(token_request_url, headers=headers, data=body)
token = client.parse_request_body_response(response.text)

# Step 3: Use access token
api_url, headers, body = client.add_token('https://api.example.com/data')
api_response = requests.get(api_url, headers=headers)

Mobile Application Client

OAuth 2.0 client for mobile and single-page applications using the implicit grant. Designed for public clients that cannot securely store credentials.

class MobileApplicationClient(Client):
    def __init__(self, client_id: str, **kwargs):
        """
        Mobile application client for implicit grant.
        
        Suitable for public clients like mobile apps and single-page
        applications that cannot securely store client credentials.
        """
    
    def prepare_request_uri(
        self,
        uri: str,
        redirect_uri: str | None = None,
        scope: str | list[str] | None = None,
        state: str | None = None,
        **kwargs,
    ) -> str:
        """Prepare implicit grant authorization request URI."""
    
    def parse_request_uri_response(
        self,
        uri: str,
        state: str | None = None,
        scope: str | list[str] | None = None,
    ) -> dict[str, str]:
        """Parse implicit grant response from redirect URI fragment."""

Legacy Application Client

OAuth 2.0 client for legacy applications using the resource owner password credentials grant. Should only be used when other flows are not feasible.

class LegacyApplicationClient(Client):
    def __init__(self, client_id: str, **kwargs):
        """
        Legacy application client for password credentials grant.
        
        Only use when authorization code or implicit grants are not feasible.
        Requires high trust between client and authorization server.
        """
    
    def prepare_request_body(
        self,
        username: str,
        password: str,
        scope: str | list[str] | None = None,
        **kwargs,
    ) -> str:
        """
        Prepare password credentials token request body.
        
        Parameters:
        - username: Resource owner username
        - password: Resource owner password
        - scope: Requested scope
        """

Backend Application Client

OAuth 2.0 client for backend applications using the client credentials grant. Used for machine-to-machine authentication without user involvement.

class BackendApplicationClient(Client):
    def __init__(self, client_id: str, **kwargs):
        """
        Backend application client for client credentials grant.
        
        Used for machine-to-machine authentication where the client
        is acting on its own behalf rather than on behalf of a user.
        """
    
    def prepare_request_body(
        self,
        scope: str | list[str] | None = None,
        **kwargs,
    ) -> str:
        """
        Prepare client credentials token request body.
        
        Parameters:
        - scope: Requested scope
        """

Service Application Client

OAuth 2.0 client for service applications using JWT bearer assertion grant. Used for secure server-to-server communication with JWT authentication.

class ServiceApplicationClient(Client):
    def __init__(self, client_id: str, **kwargs):
        """
        Service application client for JWT bearer assertion grant.
        
        Used for secure server-to-server communication using
        JSON Web Tokens for client authentication.
        """
    
    def prepare_request_body(
        self,
        private_key: str,
        subject: str,
        issuer: str,
        audience: str,
        expires_at: int | None = None,
        issued_at: int | None = None,
        extra_claims: dict[str, str] | None = None,
        scope: str | list[str] | None = None,
        **kwargs,
    ) -> str:
        """
        Prepare JWT bearer assertion token request body.
        
        Parameters:
        - private_key: Private key for JWT signing
        - subject: Subject of the JWT
        - issuer: Issuer of the JWT  
        - audience: Audience of the JWT
        - expires_at: Expiration time
        - issued_at: Issued at time
        - extra_claims: Additional JWT claims
        - scope: Requested scope
        """

Device Client

OAuth 2.0 client for device flow (RFC 8628) used by input-constrained devices. Enables authentication on devices without web browsers or with limited input capabilities.

class DeviceClient(Client):
    def __init__(self, client_id: str, **kwargs):
        """
        Device client for device authorization grant (RFC 8628).
        
        Used by input-constrained devices like smart TVs, IoT devices,
        and command-line applications.
        """
    
    def prepare_request_uri(
        self,
        uri: str,
        scope: str | list[str] | None = None,
        **kwargs,
    ) -> str:
        """Prepare device authorization request URI."""
    
    def prepare_request_body(
        self,
        device_code: str,
        **kwargs,
    ) -> str:
        """
        Prepare device token request body.
        
        Parameters:
        - device_code: Device code from device authorization response
        """
    
    def parse_request_uri_response(self, uri: str, state: str | None = None) -> dict[str, str]:
        """Parse device authorization response."""

Token Placement Constants

# Token placement options
AUTH_HEADER: str  # Place token in Authorization header
URI_QUERY: str    # Place token in URI query parameters
BODY: str         # Place token in request body

# Form encoding headers
FORM_ENC_HEADERS: dict[str, str]

Usage Patterns

Authorization Code Flow with PKCE

from oauthlib.oauth2 import WebApplicationClient
from oauthlib.common import generate_token
import requests
import secrets
import hashlib
import base64

# Create client with PKCE
client = WebApplicationClient('your-client-id')

# Generate PKCE parameters
code_verifier = client.create_code_verifier(128)
code_challenge = client.create_code_challenge(code_verifier, 'S256')

# Step 1: Authorization request
auth_url, headers, body = client.prepare_authorization_request(
    'https://auth.example.com/authorize',
    redirect_url='https://your-app.com/callback',
    scope=['read', 'write'],
    state=generate_token(),
    code_challenge=code_challenge,
    code_challenge_method='S256'
)

# Step 2: Token exchange with PKCE
token_url, headers, body = client.prepare_token_request(
    'https://auth.example.com/token',
    authorization_response='callback_url_with_code',
    redirect_url='https://your-app.com/callback',
    code_verifier=code_verifier
)

Client Credentials Flow

from oauthlib.oauth2 import BackendApplicationClient
import requests

# Create client
client = BackendApplicationClient('your-client-id')

# Prepare token request
token_url, headers, body = client.prepare_token_request(
    'https://auth.example.com/token',
    scope=['api:read', 'api:write']
)

# Add client authentication to headers
headers['Authorization'] = 'Basic ' + base64.b64encode(
    f'{client_id}:{client_secret}'.encode()
).decode()

# Get token
response = requests.post(token_url, headers=headers, data=body)
token = client.parse_request_body_response(response.text)

# Use token
api_url, headers, body = client.add_token('https://api.example.com/data')
api_response = requests.get(api_url, headers=headers)

Token Refresh

# Refresh expired token
if token.get('refresh_token'):
    refresh_url, headers, body = client.prepare_refresh_token_request(
        'https://auth.example.com/token',
        refresh_token=token['refresh_token'],
        scope=['read']  # Optional: reduced scope
    )
    
    response = requests.post(refresh_url, headers=headers, data=body)
    new_token = client.parse_request_body_response(response.text)

Install with Tessl CLI

npx tessl i tessl/pypi-oauthlib

docs

common-utilities.md

device-flow.md

error-handling.md

index.md

oauth1.md

oauth2-clients.md

oauth2-servers.md

openid-connect.md

request-validation.md

token-management.md

tile.json