pyoidc (OpenID Connect and OAuth2 Library)
pyoidc is a Python implementation of both the OAuth2 authorization framework and the OpenID Connect (OIDC) authentication layer on top of it. It provides tools for building OIDC Clients (Relying Parties) and OIDC Providers (OpenID Providers). The current version is 1.7.0, and it maintains an active release cadence with updates typically every few months, addressing bug fixes, dependency updates, and Python version compatibility.
Warnings
- breaking Python 3.7 support was removed in version 1.7.0. Projects using `oic` must upgrade to Python 3.8 or newer.
- breaking The `Client.grant_from_state()` method was removed. This method was typically used for retrieving a stored grant based on a 'state' parameter.
- breaking The `pydantic` dependency requires version 2.0 or higher since `oic` version 1.7.0. Previous versions of `pydantic` may cause compatibility issues.
- gotcha The `pyoidc` GitHub repository moved from `OpenIDC/pyoidc` to `CZ-NIC/pyoidc`. Older documentation or cloned repositories might reference the old location, leading to confusion or broken links.
Install
-
pip install oic
Imports
- Client
from oic.oic.client import Client
- Provider
from oic.oic.server import Provider
- KeyJar
from oic.utils.keyio import KeyJar
- AuthorizationRequest
from oic.oic.message import AuthorizationRequest
Quickstart
import os
from oic.oic.client import Client
from oic.utils.keyio import KeyJar
# Configure these environment variables for a real flow
ISSUER = os.environ.get("OIDC_ISSUER", "https://accounts.google.com")
CLIENT_ID = os.environ.get("OIDC_CLIENT_ID", "your_client_id_here")
CLIENT_SECRET = os.environ.get("OIDC_CLIENT_SECRET", "your_client_secret_here")
REDIRECT_URI = os.environ.get("OIDC_REDIRECT_URI", "http://localhost:8080/cb")
# 1. Initialize the OIDC Client
# A KeyJar is essential for managing cryptographic keys (e.g., for JWTs)
keyjar = KeyJar()
client = Client(client_id=CLIENT_ID, client_secret=CLIENT_SECRET, keyjar=keyjar)
print(f"Initialized OIDC Client for issuer: {ISSUER}")
try:
# 2. Discover the OIDC Provider's configuration
# This fetches endpoints, supported algorithms, etc., from the issuer.
client.provider_config(ISSUER)
print(f"Discovered OIDC Provider config for {ISSUER}")
print(f"Authorization endpoint: {client.authorization_endpoint}")
# 3. Construct an Authorization Request
# This generates the URL to which the user's browser should be redirected.
auth_req = client.construct_AuthorizationRequest(
request_args={
"scope": ["openid", "profile", "email"], # Request standard OIDC scopes
"redirect_uri": REDIRECT_URI,
"response_type": ["code"], # Request an authorization code
"state": "some_random_state_string", # CSRF protection
"nonce": "another_random_nonce_string", # Replay attack protection for ID Tokens
}
)
login_url = auth_req.request(client.authorization_endpoint)
print(f"\nUser should be redirected to:\n{login_url}")
print("\nAfter user authenticates, they will be redirected back to `REDIRECT_URI`")
print("with `code`, `state` (and potentially `id_token`, `access_token`) parameters.")
print("Further steps involve handling this redirect and exchanging the code for tokens.")
except Exception as e:
print(f"An error occurred during client setup or discovery: {e}")
print("Ensure `OIDC_ISSUER`, `OIDC_CLIENT_ID`, `OIDC_CLIENT_SECRET` are correctly configured.")
print("For a full OIDC flow, a web server is required to handle redirects.")