Session auth¶
Bounded session login with SessionAuthFlow. Demo credentials only — replace before any
deploy. Hedron is not an identity provider.
Try it (simulated)¶
Wrong password → soft redirect to /login?error=1. ada / correct-horse → signed-in panel. Docs simulation.
Demo credentials: ada / correct-horse (local learning only).
Real recipe listing with the documented soft redirect and logout flow. The Demo tab is a simplified view:
app.py
"""Session login gate (demo credentials). Local learning only."""
from __future__ import annotations
from fastapi import Form as FastAPIForm
from fastapi import Request, status
from fastapi.responses import RedirectResponse
from hedron import (
Alert,
CsrfField,
Form,
Hedron,
Page,
Stack,
SubmitButton,
Text,
TextInput,
)
app = Hedron(
title="Session auth demo",
security="standard",
explorer="off",
session_secret="replace-in-production",
)
# Demo only — never hard-code production passwords.
USERS = {"ada": "correct-horse"}
@app.action("/login", fallback="/login")
def login(
request: Request,
username: str = FastAPIForm(...),
password: str = FastAPIForm(...),
):
if USERS.get(username) != password:
return RedirectResponse("/login?error=1", status_code=status.HTTP_303_SEE_OTHER)
request.session["username"] = username
return RedirectResponse("/", status_code=status.HTTP_303_SEE_OTHER)
@app.action("/logout", fallback="/login")
def logout(request: Request):
request.session.clear()
return RedirectResponse("/login", status_code=status.HTTP_303_SEE_OTHER)
@app.page("/login")
def login_page(request: Request, error: str | None = None) -> Page | RedirectResponse:
if request.session.get("username"):
return RedirectResponse("/", status_code=status.HTTP_303_SEE_OTHER)
feedback = (
Alert("Invalid username or password.", tone="danger", title="Sign-in failed")
if error == "1"
else None
)
return Page(
Stack(
Text("Sign in (demo: ada / correct-horse)"),
feedback,
Form(
CsrfField(),
TextInput("username", value="", required=True),
TextInput("password", value="", type="password", required=True),
SubmitButton("Sign in"),
action=login,
),
),
title="Login",
)
@app.page("/")
def home(request: Request) -> Page | RedirectResponse:
username = request.session.get("username")
if not username:
# Soft landing — redirect to login instead of a bare 401.
return RedirectResponse("/login", status_code=status.HTTP_303_SEE_OTHER)
return Page(
Stack(
Text(f"Signed in as {username}"),
logout.button("Sign out"),
),
title="Home",
)
Run without cloning the monorepo¶
python -m venv .venv && source .venv/bin/activate # Windows: py -3 -m venv .venv && .\.venv\Scripts\Activate.ps1
pip install "hedron>=1.0.0" "uvicorn[standard]"
curl -fsSL https://raw.githubusercontent.com/eddiethedean/hedron/main/examples/session-auth/app.py -o app.py
uvicorn app:app --reload
Run (monorepo)¶
Open http://127.0.0.1:8000/login. Demo: ada / correct-horse.
What it shows¶
SessionAuthFlowlogin/logout composition around explicitauthenticatecallbacks- Required
RateLimitPolicyand session rotation policy - Application-owned credential check (not an IdP)
Advanced — explicit @app.page / Form¶
Lower to @app.page("/login"), @app.action, CsrfField, and manual redirects when
ejecting. See AUTH.md and Authentication.
Source: examples/session-auth.