lexigram-auth
Authentication and authorization for the Lexigram Framework — JWT, OAuth2, SAML, RBAC, and multi-tenancy.
Overview
Complete authentication and authorization stack for Lexigram — JWT, OAuth2, RBAC,
SAML, passkeys, and MFA. Provides a production-ready auth layer with multiple
authentication strategies, policy-based access control, session management, and
seamless integration with lexigram-web middleware.
Use AuthModule.configure() to register the auth bundle and protect routes with
@require_auth, @require_roles, and @require_permissions decorators.
Full documentation: docs.lexigram.dev
Install
uv add lexigram-auth
# Optional extras
uv add "lexigram-auth[oauth2,saml]"
Quick Start
from lexigram import Application
from lexigram.di.module import Module, module
from lexigram.auth import AuthModule, AuthConfig, JWTConfig
@module(imports=[
AuthModule.configure(
config=AuthConfig(
secret_key="your-secret-key",
token=JWTConfig(secret_key="your-jwt-secret"),
)
)
])
class AppModule(Module):
pass
async def main() -> None:
async with Application.boot(modules=[AppModule]) as app:
# app is running — resolve services from app.container
...
if __name__ == "__main__":
import asyncio
asyncio.run(main())
Configuration
Note:
AuthConfigrequires bothsecret_keyandtoken.secret_key— pass an explicit config viaAuthModule.configure().
Option 1 — YAML file
# application.yaml
auth:
secret_key: "your-secret-key"
token:
secret_key: "your-jwt-secret"
algorithm: "HS256"
access_token_expire: "30m"
rbac:
enabled: true
default_role: "viewer"
Option 2 — Profiles + Environment Variables (recommended)
export LEX_AUTH__SECRET_KEY=your-secret-key
export LEX_AUTH__TOKEN__SECRET_KEY=your-jwt-secret
export LEX_AUTH__TOKEN__ALGORITHM=HS256
export LEX_AUTH__RBAC__DEFAULT_ROLE=viewer
Option 3 — Python
from lexigram.auth import AuthModule, AuthConfig, JWTConfig
from lexigram.contracts.core import Duration
config = AuthConfig(
secret_key="your-secret-key",
token=JWTConfig(
secret_key="your-jwt-secret",
algorithm="HS256",
access_token_expire=Duration.minutes(30),
),
)
AuthModule.configure(config)
Config reference
| Field | Default | Env var | Description |
|---|---|---|---|
secret_key |
— | LEX_AUTH__SECRET_KEY |
Top-level signing secret (required) |
token.secret_key |
— | LEX_AUTH__TOKEN__SECRET_KEY |
JWT signing secret (required) |
token.algorithm |
HS256 |
LEX_AUTH__TOKEN__ALGORITHM |
JWT algorithm: HS256, RS256, ES256 |
token.access_token_expire |
30m |
LEX_AUTH__TOKEN__ACCESS_TOKEN_EXPIRE |
Access token lifetime (duration string, e.g. 30m, 1h30m) |
rbac.enabled |
True |
LEX_AUTH__RBAC__ENABLED |
Enable RBAC |
rbac.default_role |
viewer |
LEX_AUTH__RBAC__DEFAULT_ROLE |
Default role for new users |
Module Factory Methods
| Method | Description |
|---|---|
AuthModule.configure(...) |
Configure with explicit AuthConfig |
AuthModule.stub() |
Minimal config for testing |
Key Features
- JWT authentication — HS256/RS256, key rotation, token blacklisting
- OAuth2 / OIDC — authlib-backed: Google, GitHub, custom providers
- SAML 2.0 — Enterprise SSO via pysaml2
- Passkeys (WebAuthn) — FIDO2 device-based authentication
- MFA (TOTP) — Time-based one-time passwords
- RBAC — Role/permission inheritance with policy expressions
- Session management — Device-aware sessions with concurrency limits
- Token binding — IP address binding to prevent token theft
Testing
async with Application.boot(modules=[AuthModule.stub()]) as app:
# your test code
...
Key Source Files
| File | What it contains |
|---|---|
src/lexigram/auth/module.py |
AuthModule definition |
src/lexigram/auth/config.py |
AuthConfig, JWTConfig (+ allow_unverified_dev), RBACConfig |
src/lexigram/auth/di/bundle_provider.py |
AuthBundleProvider wiring |
src/lexigram/auth/di/sub_providers/token_provider.py |
TokenProvider (boots policy) |
src/lexigram/auth/authn/jwt.py |
JWTTokenManager implementation |
src/lexigram/auth/authn/_jwt_lifecycle.py |
verify_token (enforces policy) |
src/lexigram/auth/authz/service.py |
AuthorizationService |
JWT verification policy
lexigram-auth enforces verified-only JWT decoding by default.
| Environment | Secret present | allow_unverified_dev |
Behaviour |
|---|---|---|---|
PRODUCTION / STAGING |
yes | any | Verified-only. Boot succeeds. |
PRODUCTION / STAGING |
no | any | Raises ConfigurationError at boot. Flag ignored. |
DEVELOPMENT |
yes | any | Verified-only. Boot succeeds. |
DEVELOPMENT |
no | False (default) |
Raises ConfigurationError at boot. |
DEVELOPMENT |
no | True |
Boots. Single warning logged. Tokens decoded without signature verification. |
Enable the dev opt-in
Via environment variable:
export LEX_AUTH__TOKEN__ALLOW_UNVERIFIED_DEV=true
Via Python config:
from lexigram.auth.config import AuthConfig, JWTConfig
config = AuthConfig(
secret_key="any-placeholder",
token=JWTConfig(
secret_key="any-placeholder",
allow_unverified_dev=True,
),
)
The allow_unverified_dev flag is silently ignored in PRODUCTION and STAGING; the
service always rejects the flag in those environments and raises if no real secret is
configured. This prevents the Piccolina-style mistake of silently trusting unverified tokens
in production when a secret env-var is missing.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file lexigram_auth-0.1.3007-py3-none-any.whl.
File metadata
- Download URL: lexigram_auth-0.1.3007-py3-none-any.whl
- Upload date:
- Size: 216.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.8.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6cbea51e809e9bd87cd509c3a570705a5bf5d80d4de552d49b9e680e4afebc73
|
|
| MD5 |
6b64aa4dec4975067424d36dc502a844
|
|
| BLAKE2b-256 |
ee01c75e2b75a93bc1b01078d89c2bffb6a676957ec0bfbdbf3b475047858df0
|