{"id":10117,"library":"pyop","title":"OpenID Connect Provider (OP) library for Python","description":"pyop is an OpenID Connect Provider (OP) library in Python, enabling applications to act as identity providers. It is actively maintained with a regular release cadence, adding new features, improving compatibility, and addressing bug fixes. The current version is 3.4.2.","status":"active","version":"3.4.2","language":"en","source_language":"en","source_url":"https://github.com/IdentityPython/pyop","tags":["openid-connect","oauth2","security","authentication","provider","identity-management"],"install":[{"cmd":"pip install pyop","lang":"bash","label":"Basic Install"},{"cmd":"pip install pyop[mongo]","lang":"bash","label":"Install with MongoDB support"},{"cmd":"pip install pyop[redis]","lang":"bash","label":"Install with Redis support"}],"dependencies":[{"reason":"Core dependency for OpenID Connect protocol handling.","package":"oic","optional":false},{"reason":"Required for MongoStorage backend.","package":"pymongo","optional":true},{"reason":"Required for RedisStorage backend.","package":"redis","optional":true}],"imports":[{"note":"The Server class resides in the 'server' submodule, not directly under 'pyop'.","wrong":"from pyop import Server","symbol":"Server","correct":"from pyop.server import Server"},{"note":"Storage backends are in the 'storage' submodule.","wrong":"from pyop.server.storage import DictStorage","symbol":"DictStorage","correct":"from pyop.storage import DictStorage"}],"quickstart":{"code":"import os\nfrom pyop.server import Server\nfrom pyop.storage import DictStorage\n\ndef create_op_server():\n    # In a real application, configuration would be loaded from a file or environment\n    OP_BASE_URL = os.environ.get('OP_BASE_URL', 'http://localhost:8090')\n    JWKS_URI = f'{OP_BASE_URL}/jwks.json'\n\n    # Client information (for registered clients)\n    # In a real scenario, this would come from a client registration process/database\n    CLIENTS = {\n        'test_client': {\n            'client_id': 'test_client',\n            'client_secret': 'test_secret',\n            'redirect_uris': ['http://localhost:8000/cb'],\n            'response_types': ['code', 'id_token', 'code id_token'],\n            'scope': ['openid', 'profile', 'email'],\n            'subject_type': 'pairwise'\n        }\n    }\n\n    # In-memory storage for demonstration purposes\n    # For production, use MongoStorage, RedisStorage, or a custom persistent storage\n    storage = DictStorage()\n    storage.store_clients(CLIENTS)\n\n    # Minimal server configuration\n    server_config = {\n        'issuer': OP_BASE_URL,\n        'jwks_uri': JWKS_URI,\n        'authentication_methods': ['client_secret_basic'],\n        'response_types_supported': ['code', 'id_token', 'code id_token'],\n        'subject_types_supported': ['pairwise'],\n        'scopes_supported': ['openid', 'profile', 'email'],\n        'claims_supported': ['sub', 'name', 'email', 'given_name', 'family_name']\n    }\n\n    op_server = Server(server_config, storage)\n    print(f\"OpenID Connect Provider Server initialized with issuer: {op_server.configuration.issuer}\")\n    return op_server\n\nif __name__ == '__main__':\n    # Example usage: this only initializes the server, does not run a web server.\n    # A production app would integrate this into Flask, Django, FastAPI, etc.\n    # Example: op_server.handle_authentication_request(request_params, session_id)\n    op = create_op_server()\n    # You would then integrate 'op' with your web framework to handle OIDC endpoints.","lang":"python","description":"This quickstart demonstrates how to initialize a basic pyop OpenID Connect Provider (OP) server using an in-memory dictionary storage. It sets up essential configuration like the issuer, JWKS URI, supported response types, and client information. For production environments, you would replace `DictStorage` with a persistent storage solution (e.g., `MongoStorage`, `RedisStorage`) and integrate the `Server` instance with your web framework (e.g., Flask, Django) to handle incoming OIDC requests at appropriate endpoints."},"warnings":[{"fix":"Review the v3.0.0 release notes and update any custom scope handling logic to align with the new implementation. Be prepared for changes in how custom scopes are defined and processed.","message":"Version 3.0.0 reverted support for 'additional scopes' introduced in v2.1.0 and reimplemented it in a non-backwards compatible way.","severity":"breaking","affected_versions":"<3.0.0 to 3.0.0+"},{"fix":"Ensure that your client applications use S256 (SHA256) as the code challenge method for PKCE, as plaintext (plain) is not supported by pyop.","message":"When using PKCE support (introduced in v3.3.0), the library explicitly states that 'plaintext support is missing'.","severity":"gotcha","affected_versions":"<3.3.0 to 3.3.0+"},{"fix":"Upgrade to pyop version 3.4.1 or newer if you are using PyMongo 4. Alternatively, downgrade PyMongo to a compatible version (e.g., PyMongo 3.x) for older pyop versions.","message":"Prior to v3.4.1, pyop had compatibility issues with PyMongo 4, potentially leading to errors when using MongoStorage.","severity":"gotcha","affected_versions":"3.0.0 - 3.4.0"},{"fix":"Review the documentation for the stateless code flow in v3.4.0+. If your application implicitly relied on state for certain operations, verify behavior or explicitly configure state management as needed.","message":"Version 3.4.0 introduced support for a stateless code flow. If your application relies on stateful operations, upgrading might require attention to ensure existing state management patterns are compatible or if explicit stateless handling is desired.","severity":"gotcha","affected_versions":"3.0.0 - 3.3.x to 3.4.0+"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Upgrade pyop to version 3.4.1 or higher to ensure compatibility with PyMongo 4. Alternatively, if you cannot upgrade pyop, downgrade your PyMongo version to 3.x.","cause":"This error typically indicates an incompatibility between an older version of pyop's MongoStorage and PyMongo 4, which has stricter naming conventions.","error":"pymongo.errors.CollectionInvalid: collection names must not start or end with '.' or contain '$'"},{"fix":"The 'additional scopes' feature was re-implemented in a non-backwards compatible way in v3.0.0. Consult the release notes for v3.0.0 and update your custom scope definition and retrieval logic accordingly.","cause":"This error or similar issues related to custom scope handling often arise after upgrading to pyop v3.0.0 due to a breaking change in how additional scopes are managed.","error":"AttributeError: 'Server' object has no attribute 'get_additional_scopes'"},{"fix":"Upgrade pyop to version 3.4.1 or higher to resolve the bug related to `None` user IDs in stateless userinfo handling.","cause":"A bug existed in pyop versions prior to 3.4.1 where userinfo handling in stateless mode could lead to `TypeError` if a user ID was `None`.","error":"TypeError: argument of type 'NoneType' is not iterable in userinfo handling"}]}