OIDC helper library
Project description
py-identity-model
OIDC helper library. This project is very limited in functionality, but it has been used in production for years as the foundation of Flask/FastAPI middleware implementations.
Does not currently support opaque tokens.
Inspired By:
Examples
Discovery
Only a subset of fields is currently mapped.
import os
from py_identity_model import DiscoveryDocumentRequest, get_discovery_document
DISCO_ADDRESS = os.environ["DISCO_ADDRESS"]
disco_doc_request = DiscoveryDocumentRequest(address=DISCO_ADDRESS)
disco_doc_response = get_discovery_document(disco_doc_request)
print(disco_doc_response)
JWKs
import os
from py_identity_model import (
DiscoveryDocumentRequest,
get_discovery_document,
JwksRequest,
get_jwks,
)
DISCO_ADDRESS = os.environ["DISCO_ADDRESS"]
disco_doc_request = DiscoveryDocumentRequest(address=DISCO_ADDRESS)
disco_doc_response = get_discovery_document(disco_doc_request)
jwks_request = JwksRequest(address=disco_doc_response.jwks_uri)
jwks_response = get_jwks(jwks_request)
print(jwks_response)
Basic Token Validation
Token validation validates the signature of a JWT against the values provided from an OIDC discovery document. The function will throw an exception if the token is expired or signature validation fails.
Token validation is simply a wrapper on top of the jose.jwt.decode. The configuration object is mapped to the input parameters of jose.jwt.decode
.
@dataclass
class TokenValidationConfig:
perform_disco: bool
key: Optional[dict] = None
audience: Optional[str] = None
algorithms: Optional[List[str]] = None
issuer: Optional[List[str]] = None
subject: Optional[str] = None
options: Optional[dict] = None
import os
from py_identity_model import PyIdentityModelException, validate_token
DISCO_ADDRESS = os.environ["DISCO_ADDRESS"]
token = get_token() # Get the token in the manner best suited to your application
validation_options = {
"verify_signature": True,
"verify_aud": True,
"verify_iat": True,
"verify_exp": True,
"verify_nbf": True,
"verify_iss": True,
"verify_sub": True,
"verify_jti": True,
"verify_at_hash": True,
"require_aud": False,
"require_iat": False,
"require_exp": False,
"require_nbf": False,
"require_iss": False,
"require_sub": False,
"require_jti": False,
"require_at_hash": False,
"leeway": 0,
}
validation_config = TokenValidationConfig(
perform_disco=True,
audience=TEST_AUDIENCE,
options=validation_options
)
claims = validate_token(jwt=token, disco_doc_address=DISCO_ADDRESS)
print(claims)
Token Generation
The only current supported flow is the client_credentials
flow. Load configuration parameters in the method your application supports. Environment variables are used here for demonstration purposes.
Example:
import os
from py_identity_model import (
ClientCredentialsTokenRequest,
request_client_credentials_token,
get_discovery_document,
DiscoveryDocumentRequest,
)
DISCO_ADDRESS = os.environ["DISCO_ADDRESS"]
CLIENT_ID = os.environ["CLIENT_ID"]
CLIENT_SECRET = os.environ["CLIENT_SECRET"]
SCOPE = os.environ["SCOPE"]
disco_doc_response = get_discovery_document(
DiscoveryDocumentRequest(address=DISCO_ADDRESS)
)
client_creds_req = ClientCredentialsTokenRequest(
client_id=CLIENT_ID,
client_secret=CLIENT_SECRET,
address=disco_doc_response.token_endpoint,
scope=SCOPE,
)
client_creds_token = request_client_credentials_token(client_creds_req)
print(client_creds_token)
Roadmap
These are in no particular order of importance. I am working on this project to bring a library as capable as IdentityModel to the Python ecosystem and will most likely focus on the needful and most used features first.
- Protocol abstractions and constants
- Discovery Endpoint
- Token Endpoint
- Token Introspection Endpoint
- Token Revocation Endpoint
- UserInfo Endpoint
- Dynamic Client Registration
- Device Authorization Endpoint
- Token Validation
- Example integrations with popular providers
- Example middleware implementations for Flask and FastApi
- async Support
- Setup documentation
- Opaque tokens
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.