CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-authlib

The ultimate Python library in building OAuth and OpenID Connect servers and clients.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

common-utilities.mddocs/

Common Utilities

Shared utilities for encoding, security operations, URL handling, and error management used throughout the Authlib library. Provides consistent behavior, security best practices, and foundational functionality for all OAuth and JOSE operations.

Capabilities

Encoding and Serialization

Utilities for encoding, decoding, and serializing data in various formats used by OAuth and JOSE standards.

def to_bytes(x: str, charset: str = "utf-8", errors: str = "strict") -> bytes:
    """
    Convert string to bytes using specified encoding.
    
    Args:
        x: String to convert
        charset: Character encoding to use
        errors: Error handling strategy
        
    Returns:
        Bytes representation of the string
    """

def to_unicode(x, charset: str = "utf-8", errors: str = "strict") -> str:
    """
    Convert bytes or string to unicode string.
    
    Args:
        x: Bytes or string to convert
        charset: Character encoding to use
        errors: Error handling strategy
        
    Returns:
        Unicode string representation
    """

def to_native(x, encoding: str = "ascii") -> str:
    """
    Convert to native string type for the platform.
    
    Args:
        x: Input to convert
        encoding: Character encoding to use
        
    Returns:
        Native string representation
    """

def json_loads(s: str) -> dict:
    """
    Deserialize JSON string to Python object.
    
    Args:
        s: JSON string to deserialize
        
    Returns:
        Deserialized Python object
    """

def json_dumps(data: object, ensure_ascii: bool = False) -> str:
    """
    Serialize Python object to JSON string.
    
    Args:
        data: Python object to serialize
        ensure_ascii: Whether to escape non-ASCII characters
        
    Returns:
        JSON string representation
    """

def urlsafe_b64decode(s: str) -> bytes:
    """
    Decode URL-safe base64 string.
    
    Args:
        s: URL-safe base64 string to decode
        
    Returns:
        Decoded bytes
    """

def urlsafe_b64encode(s: bytes) -> str:
    """
    Encode bytes as URL-safe base64 string.
    
    Args:
        s: Bytes to encode
        
    Returns:
        URL-safe base64 string
    """

def base64_to_int(s: str) -> int:
    """
    Convert base64 string to integer.
    
    Args:
        s: Base64 string representing an integer
        
    Returns:
        Integer value
    """

def int_to_base64(num: int) -> str:
    """
    Convert integer to base64 string.
    
    Args:
        num: Integer to convert
        
    Returns:
        Base64 string representation
    """

def json_b64encode(text: str) -> str:
    """
    JSON encode then base64 encode text.
    
    Args:
        text: Text to encode
        
    Returns:
        Base64-encoded JSON string
    """

Security Utilities

Security functions for token generation, transport validation, and cryptographic operations.

# Character set for token generation
UNICODE_ASCII_CHARACTER_SET: str

def generate_token(length: int = 30, chars: str = UNICODE_ASCII_CHARACTER_SET) -> str:
    """
    Generate cryptographically secure random token.
    
    Args:
        length: Length of token to generate
        chars: Character set to use for token generation
        
    Returns:
        Random token string
    """

def is_secure_transport(uri: str) -> bool:
    """
    Check if URI uses secure transport (HTTPS).
    
    Args:
        uri: URI to check
        
    Returns:
        True if URI uses secure transport
    """

URL Utilities

Comprehensive URL handling utilities for OAuth parameter encoding, decoding, and manipulation.

def url_encode(params: dict) -> str:
    """
    URL-encode parameters dictionary.
    
    Args:
        params: Dictionary of parameters to encode
        
    Returns:
        URL-encoded parameter string
    """

def url_decode(query: str) -> dict:
    """
    URL-decode query string with validation.
    
    Args:
        query: Query string to decode
        
    Returns:
        Dictionary of decoded parameters
    """

def add_params_to_qs(query: str, params: dict) -> str:
    """
    Add parameters to existing query string.
    
    Args:
        query: Existing query string
        params: Parameters to add
        
    Returns:
        Updated query string
    """

def add_params_to_uri(uri: str, params: dict, fragment: bool = False) -> str:
    """
    Add parameters to URI.
    
    Args:
        uri: Base URI
        params: Parameters to add
        fragment: Whether to add to fragment instead of query
        
    Returns:
        URI with added parameters
    """

def quote(s: str, safe: bytes = b"/") -> str:
    """
    URL quote string with specified safe characters.
    
    Args:
        s: String to quote
        safe: Characters to leave unquoted
        
    Returns:
        URL-quoted string
    """

def unquote(s: str) -> str:
    """
    URL unquote string.
    
    Args:
        s: String to unquote
        
    Returns:
        Unquoted string
    """

def quote_url(s: str) -> str:
    """
    Quote URL with extended safe characters for OAuth.
    
    Args:
        s: URL to quote
        
    Returns:
        Quoted URL string
    """

def extract_params(raw: object) -> dict:
    """
    Extract parameters from various formats (dict, list, string).
    
    Args:
        raw: Raw parameter data
        
    Returns:
        Dictionary of extracted parameters
    """

def is_valid_url(url: str, fragments_allowed: bool = True) -> bool:
    """
    Validate URL format.
    
    Args:
        url: URL to validate
        fragments_allowed: Whether fragments (#) are allowed
        
    Returns:
        True if URL is valid
    """

Error Handling

Comprehensive error handling classes for different OAuth and JOSE scenarios.

class AuthlibBaseError(Exception):
    """
    Base exception class for all Authlib errors.
    
    Provides common error handling functionality for OAuth and JOSE operations.
    """
    
    error: str = None
    error_description: str = None
    error_uri: str = None
    
    def __init__(self, error: str = None, description: str = None, uri: str = None) -> None:
        """
        Initialize base error.
        
        Args:
            error: Error code
            description: Human-readable error description
            uri: URI with error information
        """

class AuthlibHTTPError(AuthlibBaseError):
    """
    HTTP-specific error class with status codes.
    
    Used for OAuth and API errors that have HTTP status code semantics.
    """
    
    status_code: int = 400
    
    def __init__(self, error: str = None, description: str = None, uri: str = None, status_code: int = None) -> None:
        """
        Initialize HTTP error.
        
        Args:
            error: Error code
            description: Error description
            uri: Error URI
            status_code: HTTP status code
        """

class ContinueIteration(AuthlibBaseError):
    """
    Special control flow exception for continuing iteration.
    
    Used internally for flow control in OAuth grant processing.
    """
    pass

Request and Response Utilities

Utilities for handling HTTP requests and responses in OAuth flows.

class OAuth2Request:
    """OAuth 2.0 request wrapper for framework-agnostic request handling."""
    
    def __init__(self, method: str, uri: str, body: str = None, headers: dict = None) -> None:
        """
        Initialize OAuth 2.0 request wrapper.
        
        Args:
            method: HTTP method
            uri: Request URI
            body: Request body
            headers: HTTP headers dictionary
        """

class JsonRequest:
    """JSON request wrapper for API endpoints."""
    
    def __init__(self, method: str, uri: str, body: str = None, headers: dict = None) -> None:
        """
        Initialize JSON request wrapper.
        
        Args:
            method: HTTP method
            uri: Request URI
            body: JSON request body
            headers: HTTP headers dictionary
        """

class OAuth2Payload:
    """OAuth 2.0 request payload wrapper."""
    
    def __init__(self, params: dict = None) -> None:
        """
        Initialize payload wrapper.
        
        Args:
            params: Payload parameters dictionary
        """

class JsonPayload:
    """JSON payload wrapper for structured data."""
    
    def __init__(self, params: dict = None) -> None:
        """
        Initialize JSON payload wrapper.
        
        Args:
            params: JSON payload parameters
        """

Validation Utilities

Utilities for validating OAuth parameters, URIs, and other data.

def validate_redirect_uri(redirect_uri: str, allowed_uris: list = None) -> bool:
    """
    Validate OAuth redirect URI.
    
    Args:
        redirect_uri: Redirect URI to validate
        allowed_uris: List of allowed redirect URIs
        
    Returns:
        True if redirect URI is valid
    """

def validate_scope(scope: str, allowed_scopes: list = None) -> bool:
    """
    Validate OAuth scope parameter.
    
    Args:
        scope: Scope string to validate
        allowed_scopes: List of allowed scopes
        
    Returns:
        True if scope is valid
    """

def validate_response_type(response_type: str, allowed_types: list = None) -> bool:
    """
    Validate OAuth response type.
    
    Args:
        response_type: Response type to validate
        allowed_types: List of allowed response types
        
    Returns:
        True if response type is valid
    """

def validate_grant_type(grant_type: str, allowed_grants: list = None) -> bool:
    """
    Validate OAuth grant type.
    
    Args:
        grant_type: Grant type to validate
        allowed_grants: List of allowed grant types
        
    Returns:
        True if grant type is valid
    """

Usage Examples

Token Generation

from authlib.common.security import generate_token

# Generate random access token
access_token = generate_token(32)
print(f"Access token: {access_token}")

# Generate client secret
client_secret = generate_token(48)
print(f"Client secret: {client_secret}")

# Generate with custom character set
import string
alphanumeric = string.ascii_letters + string.digits
short_token = generate_token(16, alphanumeric)
print(f"Short token: {short_token}")

URL Parameter Handling

from authlib.common.urls import url_encode, url_decode, add_params_to_uri, is_valid_url

# Encode parameters for OAuth requests
params = {
    'client_id': 'my-client-id',
    'redirect_uri': 'https://example.com/callback',
    'scope': 'read write',
    'state': 'random-state-value'
}
query_string = url_encode(params)
print(f"Query string: {query_string}")

# Decode query string from callback
callback_query = "code=abc123&state=random-state-value"
decoded_params = url_decode(callback_query)
print(f"Decoded params: {decoded_params}")

# Add parameters to authorization URL
base_url = "https://provider.com/authorize"
auth_url = add_params_to_uri(base_url, params)
print(f"Authorization URL: {auth_url}")

# Validate redirect URIs
valid_uris = [
    "https://example.com/callback",
    "https://app.example.com/oauth/callback"
]

for uri in valid_uris:
    if is_valid_url(uri):
        print(f"Valid URI: {uri}")

Encoding and Serialization

from authlib.common.encoding import (
    json_loads, json_dumps, urlsafe_b64encode, urlsafe_b64decode,
    to_bytes, to_unicode
)

# JSON operations
data = {'user_id': 123, 'username': 'alice', 'scopes': ['read', 'write']}
json_string = json_dumps(data)
print(f"JSON: {json_string}")

parsed_data = json_loads(json_string)
print(f"Parsed: {parsed_data}")

# Base64 operations for JWT
payload = json_dumps(data)
payload_bytes = to_bytes(payload)
encoded_payload = urlsafe_b64encode(payload_bytes)
print(f"Base64 payload: {encoded_payload}")

# Decode
decoded_bytes = urlsafe_b64decode(encoded_payload)
decoded_string = to_unicode(decoded_bytes)
original_data = json_loads(decoded_string)
print(f"Original data: {original_data}")

Error Handling

from authlib.common.errors import AuthlibHTTPError, AuthlibBaseError

def validate_client_credentials(client_id, client_secret):
    """Example function that validates client credentials."""
    
    if not client_id:
        raise AuthlibHTTPError(
            error='invalid_client',
            description='Client ID is required',
            status_code=400
        )
    
    if not client_secret:
        raise AuthlibHTTPError(
            error='invalid_client', 
            description='Client secret is required',
            status_code=400
        )
    
    # Check credentials in database
    client = get_client_by_id(client_id)
    if not client or not client.check_secret(client_secret):
        raise AuthlibHTTPError(
            error='invalid_client',
            description='Invalid client credentials',
            status_code=401
        )
    
    return client

# Usage with error handling
try:
    client = validate_client_credentials('client-id', 'wrong-secret')
except AuthlibHTTPError as error:
    print(f"HTTP Error {error.status_code}: {error.error}")
    print(f"Description: {error.error_description}")
except AuthlibBaseError as error:
    print(f"Authlib Error: {error.error}")

Security Validation

from authlib.common.security import is_secure_transport

# Validate redirect URIs for security
redirect_uris = [
    'https://example.com/callback',  # Valid - HTTPS
    'http://localhost:8080/callback',  # Valid - localhost HTTP allowed
    'http://example.com/callback',     # Invalid - HTTP not allowed for production
    'custom-app://oauth/callback'      # Valid - custom scheme for mobile apps
]

for uri in redirect_uris:
    if is_secure_transport(uri) or uri.startswith('http://localhost'):
        print(f"✓ Secure: {uri}")
    else:
        print(f"✗ Insecure: {uri}")

Request Wrapping

from authlib.common.urls import extract_params
from authlib.oauth2 import OAuth2Request

# Create OAuth 2.0 request wrapper
def create_oauth_request(flask_request):
    """Convert Flask request to OAuth2Request."""
    
    # Extract parameters from various sources
    query_params = extract_params(flask_request.args)
    form_params = extract_params(flask_request.form)
    json_params = extract_params(flask_request.get_json() or {})
    
    # Combine all parameters
    all_params = {**query_params, **form_params, **json_params}
    
    # Create OAuth request wrapper
    oauth_request = OAuth2Request(
        method=flask_request.method,
        uri=flask_request.url,
        body=flask_request.get_data(),
        headers=dict(flask_request.headers)
    )
    
    # Add parsed parameters
    oauth_request.data = all_params
    
    return oauth_request

# Usage in Flask view
@app.route('/token', methods=['POST'])
def token_endpoint():
    oauth_request = create_oauth_request(request)
    
    # Process OAuth request
    try:
        response = authorization_server.create_token_response(oauth_request)
        return response
    except AuthlibHTTPError as error:
        return {'error': error.error, 'error_description': error.error_description}, error.status_code

Custom Validation

def validate_oauth_parameters(request):
    """Validate common OAuth parameters."""
    
    # Validate required parameters
    required_params = ['client_id', 'response_type']
    for param in required_params:
        if not request.data.get(param):
            raise AuthlibHTTPError(
                error='invalid_request',
                description=f'Missing required parameter: {param}'
            )
    
    # Validate redirect URI format
    redirect_uri = request.data.get('redirect_uri')
    if redirect_uri and not is_valid_url(redirect_uri):
        raise AuthlibHTTPError(
            error='invalid_request',
            description='Invalid redirect URI format'
        )
    
    # Validate response type
    response_type = request.data.get('response_type')
    allowed_response_types = ['code', 'token', 'id_token']
    if response_type not in allowed_response_types:
        raise AuthlibHTTPError(
            error='unsupported_response_type',
            description=f'Response type "{response_type}" is not supported'
        )
    
    return True

# Usage in authorization endpoint
@app.route('/authorize')
def authorize():
    oauth_request = create_oauth_request(request)
    
    try:
        validate_oauth_parameters(oauth_request)
        # Continue with authorization flow
    except AuthlibHTTPError as error:
        return redirect(f"{oauth_request.data['redirect_uri']}?error={error.error}&error_description={error.error_description}")

Install with Tessl CLI

npx tessl i tessl/pypi-authlib

docs

common-utilities.md

django-integration.md

flask-integration.md

http-clients.md

index.md

jose.md

oauth1.md

oauth2.md

oidc.md

tile.json