CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-python3-openid

OpenID support for modern servers and consumers with comprehensive authentication functionality.

Pending
Overview
Eval results
Files

consumer-auth.mddocs/

Consumer Authentication

Complete OpenID consumer implementation for web applications acting as relying parties. The consumer handles the full authentication flow from discovery through response processing, supporting both immediate and setup authentication modes.

Capabilities

Consumer Initialization

Initialize an OpenID consumer with session storage and an OpenID store backend.

class Consumer:
    def __init__(self, session, store, consumer_class=None):
        """
        Initialize OpenID consumer.
        
        Parameters:
        - session: dict-like session storage for the consumer
        - store: OpenIDStore instance for persistent storage
        - consumer_class: Optional custom consumer class (defaults to GenericConsumer)
        """

    def setAssociationPreference(self, association_preferences):
        """
        Set association preferences for this consumer.
        
        Parameters:
        - association_preferences: List of (association_type, session_type) tuples
        """

Authentication Flow

Start and complete the OpenID authentication process with discovery and response handling.

def begin(self, user_url, anonymous=False):
    """
    Start OpenID authentication for a user URL.
    
    Parameters:
    - user_url: str, user's OpenID identifier URL
    - anonymous: bool, whether to request anonymous authentication
    
    Returns:
    AuthRequest object for redirecting user to identity provider
    
    Raises:
    DiscoveryFailure: if discovery fails for the user URL
    """

def beginWithoutDiscovery(self, service, anonymous=False):
    """
    Start authentication with a known service endpoint.
    
    Parameters:
    - service: OpenIDServiceEndpoint object
    - anonymous: bool, whether to request anonymous authentication
    
    Returns:
    AuthRequest object
    """

def complete(self, query, current_url):
    """
    Complete OpenID authentication from identity provider response.
    
    Parameters:
    - query: dict, query parameters from identity provider response
    - current_url: str, current page URL for verification
    
    Returns:
    Response object (SuccessResponse, FailureResponse, CancelResponse, or SetupNeededResponse)
    """

Authentication Request

Represents an OpenID authentication request that can be used to redirect users or generate HTML forms.

class AuthRequest:
    def setAnonymous(self, is_anonymous):
        """
        Set whether this request should be anonymous.
        
        Parameters:
        - is_anonymous: bool, anonymous flag
        """

    def addExtension(self, extension_request):
        """
        Add an OpenID extension to this authentication request.
        
        Parameters:
        - extension_request: Extension request object (SRegRequest, FetchRequest, etc.)
        """

    def addExtensionArg(self, namespace, key, value):
        """
        Add an extension argument directly.
        
        Parameters:
        - namespace: str, extension namespace URI
        - key: str, argument key
        - value: str, argument value
        """

    def getMessage(self, realm, return_to=None, immediate=False):
        """
        Get the OpenID message for this request.
        
        Parameters:
        - realm: str, trust root/realm URL
        - return_to: str, return URL after authentication
        - immediate: bool, whether to use immediate mode
        
        Returns:
        Message object
        """

    def redirectURL(self, realm, return_to=None, immediate=False):
        """
        Get redirect URL for sending user to identity provider.
        
        Parameters:
        - realm: str, trust root/realm URL  
        - return_to: str, return URL after authentication
        - immediate: bool, whether to use immediate mode
        
        Returns:
        str, redirect URL
        """

    def formMarkup(self, realm, return_to=None, immediate=False, form_tag_attrs=None):
        """
        Generate HTML form for POST-based authentication.
        
        Parameters:
        - realm: str, trust root/realm URL
        - return_to: str, return URL after authentication
        - immediate: bool, whether to use immediate mode
        - form_tag_attrs: dict, additional HTML form attributes
        
        Returns:
        str, HTML form markup
        """

    def htmlMarkup(self, realm, return_to=None, immediate=False, form_tag_attrs=None):
        """
        Generate complete HTML page with auto-submitting form.
        
        Parameters:
        - realm: str, trust root/realm URL
        - return_to: str, return URL after authentication
        - immediate: bool, whether to use immediate mode
        - form_tag_attrs: dict, additional HTML form attributes
        
        Returns:
        str, complete HTML page
        """

    def shouldSendRedirect(self):
        """
        Check if redirect should be used instead of POST form.
        
        Returns:
        bool, True if redirect is recommended
        """

Response Handling

Process responses from identity providers with status checking and data extraction.

class Response:
    """Base class for OpenID authentication responses."""
    
    status = None
    
    def setEndpoint(self, endpoint):
        """
        Set the endpoint for this response.
        
        Parameters:
        - endpoint: OpenIDServiceEndpoint or None
        """
    
    def getDisplayIdentifier(self):
        """
        Return the display identifier for this response.
        
        The display identifier is related to the Claimed Identifier, but the
        two are not always identical. The display identifier is something the
        user should recognize as what they entered, whereas the response's
        claimed identifier may have extra information for better persistence.
        
        Returns:
        str or None, display identifier for user interface
        """

class SuccessResponse(Response):
    """Successful authentication response with status SUCCESS."""
    
    def isOpenID1(self):
        """
        Check if response uses OpenID 1.x protocol.
        
        Returns:
        bool, True if OpenID 1.x
        """

    def isSigned(self, ns_uri, ns_key):
        """
        Check if a specific field is signed in the response.
        
        Parameters:
        - ns_uri: str, namespace URI
        - ns_key: str, field key
        
        Returns:
        bool, True if field is signed
        """

    def getSigned(self, ns_uri, ns_key, default=None):
        """
        Get a signed field value from the response.
        
        Parameters:
        - ns_uri: str, namespace URI
        - ns_key: str, field key
        - default: default value if field not found
        
        Returns:
        str or default, field value
        """

    def getSignedNS(self, ns_uri):
        """
        Get all signed fields in a namespace.
        
        Parameters:
        - ns_uri: str, namespace URI
        
        Returns:
        dict, signed fields in namespace
        """

    def extensionResponse(self, namespace_uri, require_signed):
        """
        Extract extension data from response.
        
        Parameters:
        - namespace_uri: str, extension namespace URI
        - require_signed: bool, whether to require signed data
        
        Returns:
        dict, extension data
        """

    def getReturnTo(self):
        """
        Get the return_to URL from response.
        
        Returns:
        str, return_to URL
        """

class FailureResponse(Response):
    """Failed authentication response with status FAILURE."""
    
    def __init__(self, endpoint, message=None, contact=None, reference=None):
        """
        Initialize a failure response.
        
        Parameters:
        - endpoint: OpenIDServiceEndpoint or None
        - message: str or None, failure reason message
        - contact: str or None, contact information for support
        - reference: str or None, reference identifier for this failure
        """
    
    # Attributes:
    # message: str or None - failure reason message
    # contact: str or None - contact information for support  
    # reference: str or None - reference identifier for this failure

class CancelResponse(Response):
    """User-cancelled authentication response with status CANCEL."""
    
    def __init__(self, endpoint):
        """
        Initialize a cancel response.
        
        Parameters:
        - endpoint: OpenIDServiceEndpoint or None
        """

class SetupNeededResponse(Response):
    """Setup needed for immediate mode response with status SETUP_NEEDED."""
    
    def __init__(self, endpoint, setup_url=None):
        """
        Initialize a setup needed response.
        
        Parameters:
        - endpoint: OpenIDServiceEndpoint or None
        - setup_url: str or None, URL for user setup (OpenID 1.x only)
        """
    
    # Attributes:
    # setup_url: str or None - URL that can be used to send the user to the
    # server to set up for authentication. None in OpenID 2.0.

Usage Examples

Basic Consumer Implementation

from openid.consumer import consumer
from openid.store.filestore import FileOpenIDStore

# Initialize consumer
store = FileOpenIDStore('/tmp/openid_store')
openid_consumer = consumer.Consumer({}, store)

# Start authentication
user_url = "https://example.com/user"
try:
    auth_request = openid_consumer.begin(user_url)
    redirect_url = auth_request.redirectURL(
        realm="https://mysite.com",
        return_to="https://mysite.com/openid/complete"
    )
    # Redirect user to redirect_url
except consumer.DiscoveryFailure as e:
    print(f"Discovery failed: {e}")

Complete Authentication Flow

# Handle return from identity provider
def handle_openid_return(request):
    query = dict(request.GET.items())
    current_url = request.build_absolute_uri()
    
    response = openid_consumer.complete(query, current_url)
    
    if response.status == consumer.SUCCESS:
        print(f"Success! Identity URL: {response.identity_url}")
        print(f"Display identifier: {response.getDisplayIdentifier()}")
        
        # Extract extension data if present
        sreg_response = sreg.SRegResponse.fromSuccessResponse(response)
        if sreg_response:
            email = sreg_response.get('email')
            nickname = sreg_response.get('nickname')
            
    elif response.status == consumer.FAILURE:
        print(f"Authentication failed: {response.message}")
    elif response.status == consumer.CANCEL:
        print("Authentication cancelled by user")
    elif response.status == consumer.SETUP_NEEDED:
        print(f"Setup needed at: {response.setup_url}")

Using Extensions

from openid.extensions import sreg

# Add SREG extension to request
auth_request = openid_consumer.begin(user_url)
sreg_request = sreg.SRegRequest(
    required=['nickname', 'email'],
    optional=['fullname'],
    policy_url="https://mysite.com/privacy"
)
auth_request.addExtension(sreg_request)

redirect_url = auth_request.redirectURL(
    realm="https://mysite.com",
    return_to="https://mysite.com/openid/complete"
)

Types

# Response status constants
SUCCESS = 'success'
FAILURE = 'failure'
CANCEL = 'cancel' 
SETUP_NEEDED = 'setup_needed'

# Exception types
class ProtocolError(ValueError):
    """
    OpenID protocol violation exception.
    
    Raised when a message violates the OpenID protocol specification.
    This is caught internally and converted to FailureResponse objects.
    """

class DiscoveryFailure(Exception):
    """
    Discovery process failed exception.
    
    Raised when OpenID discovery fails for a given identifier URL.
    This can happen due to network issues, invalid URLs, or missing
    OpenID service information.
    """

class SetupNeededError(Exception):
    """
    Setup needed in immediate mode exception.
    
    Internally-used exception that indicates an immediate-mode request
    was cancelled because user setup is required.
    """
    
    def __init__(self, user_setup_url=None):
        """
        Initialize setup needed error.
        
        Parameters:
        - user_setup_url: str or None, URL for user setup
        """

class TypeURIMismatch(ProtocolError):
    """
    Type URI mismatch protocol error.
    
    Raised when expected OpenID type URIs don't match discovered
    service endpoint type URIs during verification.
    """
    
    def __init__(self, expected, endpoint):
        """
        Initialize type URI mismatch error.
        
        Parameters:
        - expected: str, expected type URI
        - endpoint: OpenIDServiceEndpoint, discovered endpoint
        """

class ServerError(Exception):
    """
    Server-side error in OpenID response.
    
    Raised when the OpenID server returns a 400 response code
    to a direct request, indicating a server-side error condition.
    """
    
    def __init__(self, error_text, error_code, message):
        """
        Initialize server error.
        
        Parameters:
        - error_text: str, error message text
        - error_code: str or None, error code from server
        - message: Message, full OpenID message containing error
        """
    
    @classmethod
    def fromMessage(cls, message):
        """
        Generate ServerError from OpenID error message.
        
        Parameters:
        - message: Message, OpenID message containing error information
        
        Returns:
        ServerError instance
        """

Install with Tessl CLI

npx tessl i tessl/pypi-python3-openid

docs

association-management.md

consumer-auth.md

discovery.md

extensions.md

index.md

message-processing.md

server-implementation.md

storage-backends.md

utilities.md

tile.json