Session Cookie Guard¶
session_cookie(*, store, secret, cookie_name, user_builder, realm) — loads sessions from a signed cookie and validates that the session is active.
Signature¶
def session_cookie(
*,
store: SessionStore,
secret: str | bytes,
cookie_name: str = "lauren_session",
user_builder: Callable[[Session], AuthUser | None] | None = None,
realm: str = "lauren",
) -> type:
...
Parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
store |
SessionStore |
— | Session backend (e.g. InMemorySessionStore). |
secret |
str \| bytes |
— | HMAC signing key for the cookie value (see sign_cookie/verify_cookie). |
cookie_name |
str |
"lauren_session" |
Cookie to read the session id from. |
user_builder |
callable | None |
None |
(Session) -> AuthUser \| None. Default builds from session.user_id plus session.data["roles"]/["scopes"]. |
realm |
str |
"lauren" |
Surfaced in error responses. |
Usage¶
from lauren_guards import InMemorySessionStore, session_cookie
store = InMemorySessionStore()
SessionGuard = session_cookie(
store=store,
secret="my-hmac-secret",
cookie_name="lauren_session",
)
Logging a user in¶
Create the session in your login handler, sign it, and set the cookie:
from lauren import Response
from lauren_guards import InMemorySessionStore, session_cookie, sign_cookie
store = InMemorySessionStore()
SECRET = "my-hmac-secret"
SessionGuard = session_cookie(store=store, secret=SECRET)
async def login(request, username: str) -> Response:
session = await store.create(user_id=username, ttl_seconds=3600)
signed = sign_cookie(session.id, secret=SECRET)
return Response.json({"ok": True}).with_cookie(
"lauren_session", signed,
http_only=True, secure=True, same_site="lax",
)
Note the cookie flags: http_only=True keeps JavaScript away from the
session id, secure=True restricts it to HTTPS, and same_site="lax"
adds CSRF mitigation.
How the guard validates requests¶
On each request the guard reads the cookie_name cookie, verifies its HMAC
signature with secret, looks up the Session in store, and checks it is
not expired. It then builds the AuthUser via user_builder (default:
session.user_id plus session.data["roles"]/["scopes"]) and stores it on
request.state.user.
See Sessions for the SessionStore protocol
and cookie utilities.
Production store¶
Swap InMemorySessionStore for a shared store by implementing the
SessionStore protocol — see the Redis-backed example in
Sessions.