Skip to main content

litestar-keycloak

PyPI version Python versions Development status License Downloads

CI Coverage Ruff Checked with mypy Typed Last commit

Keycloak authentication plugin for Litestar. OIDC/OAuth2 integration using Litestar's native plugin protocol, dependency injection, and guard system.

Features

  • OIDC discovery and JWKS caching with automatic key rotation
  • Bearer token validation (header or cookie)
  • Realm and client role guards
  • Scope-based access control
  • KeycloakUser injection via Litestar DI
  • Optional login/callback/logout route group
  • Async HTTP via aiohttp for token exchange and JWKS requests

Installation

pip install litestar-keycloak

Quick Start

from litestar import Litestar, get
from litestar_keycloak import KeycloakPlugin, KeycloakConfig, CurrentUser

@get("/me")
async def me(current_user: CurrentUser) -> dict:
    return {
        "sub": current_user.sub,
        "username": current_user.preferred_username,
        "roles": current_user.realm_roles,
    }

app = Litestar(
    route_handlers=[me],
    plugins=[KeycloakPlugin(
        KeycloakConfig(
            server_url="https://keycloak.example.com",
            realm="my-realm",
            client_id="my-app",
        )
    )],
)

Any route that declares current_user: CurrentUser automatically requires a valid Bearer token.

Guards

Restrict access by roles or scopes:

from litestar import get
from litestar_keycloak import require_roles, require_scopes

@get("/admin", guards=[require_roles("admin")])
async def admin_panel() -> dict:
    return {"msg": "welcome, admin"}

@get("/reports", guards=[require_scopes("reports:read")])
async def reports() -> dict:
    return {"msg": "here are your reports"}

Configuration

KeycloakConfig(
    server_url="https://keycloak.example.com",
    realm="my-realm",
    client_id="my-app",
    client_secret="secret",            # confidential clients
    token_location=TokenLocation.HEADER,  # HEADER (default) or COOKIE
    jwks_cache_ttl=3600,               # JWKS cache lifetime in seconds
    algorithms=("RS256",),             # JWT signing algorithms
    include_routes=False,              # mount /auth/login, /callback, /logout
    optional_audiences=frozenset({"my-service"}),  # accept service tokens too
)

Full option list: docs/configuration.md.

When include_routes=True, the plugin mounts:

Endpoint Description
GET /auth/login Redirect to Keycloak authorize
GET /auth/callback Handle authorization code exchange
POST /auth/logout End session (Keycloak + local)
POST /auth/refresh Refresh access token

Testing

Unit tests (no Keycloak required)

Test utilities live in tests/conftest.py: create_test_token() and MockKeycloakPlugin(). Use them in your tests (e.g. when running pytest from this repo, or import from conftest):

from tests.conftest import create_test_token, MockKeycloakPlugin

# Mint a fake JWT with arbitrary claims
token = create_test_token(sub="user-1", realm_roles=["admin"])

# Use MockKeycloakPlugin to skip real JWKS validation
app = Litestar(
    route_handlers=[...],
    plugins=[MockKeycloakPlugin()],
)

Integration tests (real Keycloak via testcontainers)

from testcontainers.keycloak import KeycloakContainer

kc = (
    KeycloakContainer("quay.io/keycloak/keycloak:26.0")
    .with_command("start-dev --import-realm")
    .with_volume_mapping(
        "tests/fixtures/realm-export.json",
        "/opt/keycloak/data/import/realm-export.json",
        "ro",
    )
)
kc.start()

See tests/fixtures/realm-export.json for a pre-configured realm with test users and roles.

Service-to-service

To accept tokens from a service client (e.g. client_credentials), add its client ID to optional_audiences. Use the raw_token dependency to forward the caller's token to downstream APIs. See Service-to-service.

Documentation

Dependencies

Package Purpose
litestar[standard] ≥ 2.0 Web framework (plugin target)
aiohttp Async HTTP for token/JWKS calls
PyJWT[crypto] JWT validation

License

MIT

Metadata

Release files for litestar-keycloak 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for litestar-keycloak 0.2.0
File Size Uploaded
litestar_keycloak-0.2.0.tar.gz 174.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for litestar-keycloak 0.2.0
File Interpreter ABI Platform
litestar_keycloak-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 196.7 kB

Release files / litestar_keycloak-0.2.0.tar.gz

Download URL litestar_keycloak-0.2.0.tar.gz
Size 174.9 kB
Tags Source
SHA-256 checksum
How to use checksums
9c7e7d6ca79cf37b3af0ee0725a34e5515054ad86e36e5308e38b816bebeea82
BLAKE2b-256 checksum
How to use checksums
17908c81f0548988046ea8ebe382f6de8ba5ca7b3433dd5579b656605fd1ba6b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 21, 2026.

Transparency log

Release files / litestar_keycloak-0.2.0-py3-none-any.whl

Download URL litestar_keycloak-0.2.0-py3-none-any.whl
Size 21.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
812a732146f7131049964ed67ed83cfa10bad4e20b96ab2f623b47e8f4b137ea
BLAKE2b-256 checksum
How to use checksums
6450916ce112eb78cdeb20c8110cc895028c38ab93cdb380bf00ec4fbb7099eb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 21, 2026.

Transparency log

Release history Release notifications | RSS feed

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page