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

message-processing.mddocs/

Message Processing

OpenID protocol message handling with namespace management, encoding/decoding, and format conversion. The message system provides a unified interface for working with OpenID protocol messages across different formats and versions.

Capabilities

Message Objects

Core message representation with namespace-aware argument handling and format conversion.

class Message:
    """OpenID protocol message with namespace support."""
    
    def __init__(self, openid_namespace=None):
        """
        Initialize message with optional OpenID namespace.
        
        Parameters:
        - openid_namespace: str, OpenID namespace URI (auto-detected if None)
        """

    @classmethod
    def fromPostArgs(cls, args):
        """
        Create message from POST form arguments.
        
        Parameters:
        - args: dict, form arguments (typically request.POST)
        
        Returns:
        Message object
        """

    @classmethod
    def fromOpenIDArgs(cls, openid_args):
        """
        Create message from OpenID-specific arguments.
        
        Parameters:
        - openid_args: dict, arguments with 'openid.' prefix stripped
        
        Returns:
        Message object
        """

    @classmethod
    def fromKVForm(cls, kvform_string):
        """
        Create message from key-value form string.
        
        Parameters:
        - kvform_string: str, key-value form data
        
        Returns:
        Message object
        """

    def copy(self):
        """
        Create deep copy of this message.
        
        Returns:
        Message, copy of this message
        """

    def toPostArgs(self):
        """
        Convert message to POST form arguments.
        
        Returns:
        dict, form arguments with 'openid.' prefixes
        """

    def toArgs(self):
        """
        Convert message to basic argument dictionary.
        
        Returns:
        dict, message arguments
        """

    def toFormMarkup(self, action_url, form_tag_attrs=None, submit_text="Continue"):
        """
        Generate HTML form markup for message.
        
        Parameters:
        - action_url: str, form action URL
        - form_tag_attrs: dict, additional form tag attributes
        - submit_text: str, submit button text
        
        Returns:
        str, HTML form markup
        """

    def toURL(self, base_url):
        """
        Convert message to URL with query parameters.
        
        Parameters:
        - base_url: str, base URL
        
        Returns:
        str, URL with message encoded as query parameters
        """

    def toKVForm(self):
        """
        Convert message to key-value form string.
        
        Returns:
        str, key-value form representation
        """

    def toURLEncoded(self):
        """
        Convert message to URL-encoded form data.
        
        Returns:
        str, URL-encoded form data
        """

Message Argument Handling

Access and modify message arguments with namespace support.

def hasKey(self, namespace, ns_key):
    """
    Check if message has argument in namespace.
    
    Parameters:
    - namespace: str, namespace URI or symbol
    - ns_key: str, argument key within namespace
    
    Returns:
    bool, True if argument exists
    """

def getKey(self, namespace, ns_key):
    """
    Get full argument key for namespace and key.
    
    Parameters:
    - namespace: str, namespace URI or symbol
    - ns_key: str, argument key within namespace
    
    Returns:
    str, full argument key with namespace alias
    """

def getArg(self, namespace, key, default=None):
    """
    Get argument value from namespace.
    
    Parameters:
    - namespace: str, namespace URI or symbol
    - key: str, argument key
    - default: default value if not found
    
    Returns:
    str or default, argument value
    """

def getArgs(self, namespace):
    """
    Get all arguments in namespace.
    
    Parameters:
    - namespace: str, namespace URI or symbol
    
    Returns:
    dict, {key: value} arguments in namespace
    """

def setArg(self, namespace, key, value):
    """
    Set argument value in namespace.
    
    Parameters:
    - namespace: str, namespace URI or symbol
    - key: str, argument key
    - value: str, argument value
    """

def updateArgs(self, namespace, updates):
    """
    Update multiple arguments in namespace.
    
    Parameters:
    - namespace: str, namespace URI or symbol
    - updates: dict, {key: value} updates
    """

def delArg(self, namespace, key):
    """
    Delete argument from namespace.
    
    Parameters:
    - namespace: str, namespace URI or symbol
    - key: str, argument key to delete
    """

def getAliasedArg(self, aliased_key, default=None):
    """
    Get argument by aliased key (e.g., 'openid.mode').
    
    Parameters:
    - aliased_key: str, full aliased key
    - default: default value if not found
    
    Returns:
    str or default, argument value
    """

Namespace Management

Handle OpenID namespace detection and version compatibility.

def setOpenIDNamespace(self, openid_ns_uri, implicit):
    """
    Set OpenID namespace for this message.
    
    Parameters:
    - openid_ns_uri: str, OpenID namespace URI
    - implicit: bool, whether namespace is implicit (OpenID 1.x)
    """

def getOpenIDNamespace(self):
    """
    Get OpenID namespace URI for this message.
    
    Returns:
    str, OpenID namespace URI
    """

def isOpenID1(self):
    """
    Check if message uses OpenID 1.x protocol.
    
    Returns:
    bool, True if OpenID 1.x
    """

def isOpenID2(self):
    """
    Check if message uses OpenID 2.0 protocol.
    
    Returns:
    bool, True if OpenID 2.0
    """

Namespace Mapping

Manage namespace URI to alias mappings for message encoding.

class NamespaceMap:
    """Maps namespace URIs to short aliases for message encoding."""
    
    def __init__(self):
        """Initialize empty namespace map."""

    def getAlias(self, namespace_uri):
        """
        Get alias for namespace URI.
        
        Parameters:
        - namespace_uri: str, namespace URI
        
        Returns:
        str, namespace alias or None if not defined
        """

    def getNamespaceURI(self, alias):
        """
        Get namespace URI for alias.
        
        Parameters:
        - alias: str, namespace alias
        
        Returns:
        str, namespace URI or None if not defined
        """

    def addAlias(self, namespace_uri, desired_alias, implicit=False):
        """
        Add namespace URI with desired alias.
        
        Parameters:
        - namespace_uri: str, namespace URI
        - desired_alias: str, desired alias (may be modified if conflicts)
        - implicit: bool, whether namespace is implicit
        
        Returns:
        str, actual alias assigned
        """

    def add(self, namespace_uri):
        """
        Add namespace URI with auto-generated alias.
        
        Parameters:
        - namespace_uri: str, namespace URI
        
        Returns:
        str, assigned alias
        """

    def isDefined(self, namespace_uri):
        """
        Check if namespace URI is defined.
        
        Parameters:
        - namespace_uri: str, namespace URI
        
        Returns:
        bool, True if defined
        """

    def isImplicit(self, namespace_uri):
        """
        Check if namespace is implicit (no explicit alias).
        
        Parameters:
        - namespace_uri: str, namespace URI
        
        Returns:
        bool, True if implicit
        """

    def items(self):
        """
        Get all namespace URI to alias mappings.
        
        Returns:
        list, [(namespace_uri, alias), ...] tuples
        """

Global Namespace Utilities

Utilities for managing global namespace alias registrations.

def registerNamespaceAlias(namespace_uri, alias):
    """
    Register global namespace alias for automatic assignment.
    
    Parameters:
    - namespace_uri: str, namespace URI
    - alias: str, preferred alias
    
    Raises:
    NamespaceAliasRegistrationError: if alias conflicts
    """

Usage Examples

Basic Message Creation and Access

from openid.message import Message, OPENID2_NS

# Create new message
message = Message(OPENID2_NS)

# Set basic OpenID arguments
message.setArg('openid.ns', OPENID2_NS)
message.setArg('openid.mode', 'checkid_setup')
message.setArg('openid.identity', 'https://user.example.com')
message.setArg('openid.return_to', 'https://consumer.example.com/return')

# Access arguments
mode = message.getArg('openid.ns', 'mode')
identity = message.getArg('openid.ns', 'identity')

print(f"Mode: {mode}")
print(f"Identity: {identity}")

# Check OpenID version
if message.isOpenID2():
    print("Using OpenID 2.0")
elif message.isOpenID1():
    print("Using OpenID 1.x")

Message Format Conversion

# Convert to different formats
post_args = message.toPostArgs()
print("POST arguments:", post_args)

url = message.toURL('https://op.example.com/openid')
print("URL:", url)

kvform = message.toKVForm()
print("Key-value form:")
print(kvform)

# Generate HTML form
form_html = message.toFormMarkup(
    action_url='https://op.example.com/openid',
    submit_text='Continue to Identity Provider'
)
print("HTML form:")
print(form_html)

Parsing Messages from Different Sources

# From POST data (typical web framework usage)
post_data = {
    'openid.ns': 'http://specs.openid.net/auth/2.0',
    'openid.mode': 'id_res',
    'openid.identity': 'https://user.example.com',
    'openid.sig': 'signature_value'
}
message_from_post = Message.fromPostArgs(post_data)

# From key-value form (for check_authentication)
kvform_data = """ns:http://specs.openid.net/auth/2.0
mode:id_res
identity:https://user.example.com
sig:signature_value"""
message_from_kv = Message.fromKVForm(kvform_data)

# From OpenID args (without 'openid.' prefix)
openid_args = {
    'ns': 'http://specs.openid.net/auth/2.0',
    'mode': 'id_res',
    'identity': 'https://user.example.com'
}
message_from_args = Message.fromOpenIDArgs(openid_args)

Working with Extensions

from openid.extensions import sreg

# Create message with extension
message = Message()
message.setArg('openid.ns', 'http://specs.openid.net/auth/2.0')
message.setArg('openid.mode', 'checkid_setup')

# Add SREG extension namespace
sreg_ns = 'http://openid.net/extensions/sreg/1.1'
message.setArg('openid.ns.sreg', sreg_ns)
message.setArg(sreg_ns, 'required', 'nickname,email')
message.setArg(sreg_ns, 'optional', 'fullname')

# Access extension arguments
sreg_args = message.getArgs(sreg_ns)
print("SREG arguments:", sreg_args)

# Check if extension is present
if message.hasKey(sreg_ns, 'required'):
    required_fields = message.getArg(sreg_ns, 'required')
    print(f"Required SREG fields: {required_fields}")

Namespace Management

from openid.message import NamespaceMap

# Create namespace map
ns_map = NamespaceMap()

# Add namespaces
openid_alias = ns_map.addAlias('http://specs.openid.net/auth/2.0', 'openid')
sreg_alias = ns_map.addAlias('http://openid.net/extensions/sreg/1.1', 'sreg')
ax_alias = ns_map.add('http://openid.net/srv/ax/1.0')  # Auto-generated alias

print(f"OpenID alias: {openid_alias}")
print(f"SREG alias: {sreg_alias}")
print(f"AX alias: {ax_alias}")

# Check namespace definitions
if ns_map.isDefined('http://openid.net/extensions/sreg/1.1'):
    alias = ns_map.getAlias('http://openid.net/extensions/sreg/1.1')
    print(f"SREG namespace has alias: {alias}")

# Get all mappings
for namespace_uri, alias in ns_map.items():
    print(f"{namespace_uri} -> {alias}")

Message Copying and Modification

# Create original message
original = Message()
original.setArg('openid.ns', 'http://specs.openid.net/auth/2.0')
original.setArg('openid.ns', 'mode', 'checkid_setup')
original.setArg('openid.ns', 'identity', 'https://user.example.com')

# Create copy
copy = original.copy()

# Modify copy without affecting original
copy.setArg('openid.ns', 'mode', 'checkid_immediate')
copy.setArg('openid.ns', 'return_to', 'https://consumer.example.com/return')

# Original is unchanged
print("Original mode:", original.getArg('openid.ns', 'mode'))
print("Copy mode:", copy.getArg('openid.ns', 'mode'))

Global Namespace Registration

from openid.message import registerNamespaceAlias

# Register commonly used namespace aliases
try:
    registerNamespaceAlias('http://openid.net/extensions/sreg/1.1', 'sreg')
    registerNamespaceAlias('http://openid.net/srv/ax/1.0', 'ax')
    registerNamespaceAlias('http://schemas.openid.net/pape/policies/2007/06/phishing-resistant', 'pape')
    print("Namespace aliases registered successfully")
except Exception as e:
    print(f"Failed to register alias: {e}")

# Now these aliases will be used automatically when creating messages
message = Message()
# When adding SREG extension, 'sreg' alias will be preferred

Types

# OpenID namespace URIs
OPENID1_NS = 'http://openid.net/signon/1.0'
OPENID2_NS = 'http://specs.openid.net/auth/2.0'

# Special namespace symbols
NULL_NAMESPACE = object()  # For arguments without namespace
OPENID_NS = object()       # For current OpenID namespace
BARE_NS = object()         # For bare arguments (no prefix)

# Standard OpenID arguments
IDENTIFIER_SELECT = 'http://specs.openid.net/auth/2.0/identifier_select'
SREG_URI = 'http://openid.net/sreg/1.0'

# URL length limits
OPENID1_URL_LIMIT = 2047  # Maximum URL length for OpenID 1.x

# Special sentinel for required parameters
no_default = object()

# Key-value form constants
KV_FORM_SEPARATOR = '\n'
KV_PAIR_SEPARATOR = ':'

# Exception types
class UndefinedOpenIDNamespace(Exception):
    """OpenID namespace not defined."""

class InvalidOpenIDNamespace(Exception):
    """Invalid OpenID namespace URI."""

class NamespaceAliasRegistrationError(Exception):
    """Namespace alias registration failed."""

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