lauren-guards¶
Batteries-included authentication and authorization guards for the Lauren web framework.
Every production service eventually needs the same cross-cutting auth concerns. lauren-guards ships them all as first-class Lauren guards so you can wire them in with a single decorator. The full site lives at https://lauren-framework.github.io/lauren-guards/.
What's inside¶
- Authentication — Bearer token, Basic Auth, API key, JWT (RS256/HS256/ES256), OAuth2 introspection, session cookie.
- Authorization —
require_authenticated,require_roles,require_scopes. - Cross-cutting — CSRF (double-submit-cookie), IP allowlist.
- Utilities —
BcryptHasher,Argon2Hasher,generate_token,InMemorySessionStore. - Public-route bypass —
@publicdecorator andIS_PUBLIC_KEYfor opt-out routes. - DI-managed — every guard factory returns an
@injectable(scope=SINGLETON)class; the Lauren DI container owns its lifecycle. - Composable — use guards at the global, controller, or route level; combine multiple guards with
@use_guards(GuardA, GuardB).
Installation¶
# Core guards (Bearer, Basic, API key, session cookie, CSRF, IP)
pip install lauren-guards
# JWT support (RS256/HS256/ES256)
pip install "lauren-guards[jwt]"
# OAuth2 token introspection
pip install "lauren-guards[http]"
# Password hashing — bcrypt
pip install "lauren-guards[bcrypt]"
# Password hashing — Argon2
pip install "lauren-guards[argon2]"
# Everything
pip install "lauren-guards[all]"
Quick Start¶
from lauren import LaurenFactory, controller, get, module, use_guards
from lauren_guards import bearer_token, require_scopes, AuthUser
async def verify_token(token: str) -> AuthUser | None:
"""Return an AuthUser if the token is valid, None otherwise."""
if token == "secret":
return AuthUser(id="user-1", scopes=("read", "write"))
return None
BearerGuard = bearer_token(verify=verify_token)
@use_guards(BearerGuard)
@controller("/api")
class ApiController:
@get("/profile")
@use_guards(require_scopes("read"))
async def profile(self) -> dict:
return {"ok": True}
@module(controllers=[ApiController])
class AppModule:
pass
app = LaurenFactory.create(AppModule)
Take the getting started guide for a longer walkthrough, or jump straight to the API reference.
Guard architecture¶
All guards follow Lauren's GuardProtocol:
Guards can either return False (yields 403) or raise an HTTPError subclass (e.g., UnauthorizedError for 401) to control the exact response.
The AuthUser principal record is set on request.state.user after successful authentication:
@injectable(scope=Scope.SINGLETON)
class MyGuard:
async def can_activate(self, ctx: ExecutionContext) -> bool:
user = ctx.request.state.get("user")
return user is not None
Explore¶
- Getting Started — full example with JWT guard and role-based authorization.
- Bearer Token Guard — simple token-based authentication.
- JWT Guard — RS256/HS256 JWT validation with JWKS support.
- Reference — complete API surface.
Questions? Open an issue at github.com/lauren-framework/lauren-guards.