Skip to content

Customization Guide

A quick reference pulling together every extension point covered in detail elsewhere on this site.

Database

Implement AbstractUserStore — full examples for SQLAlchemy, MongoDB/Beanie, SQLModel, and Tortoise.

warden = AuthWarden(config=config, user_store=YourUserStore())

User model fields

Extend UserInDB via extra_data (no subclass needed) or full subclassing with typed fields.

Email delivery

Swap or write your own email backend — built-ins exist for console, SMTP, SendGrid, Mailgun.

warden = AuthWarden(config=config, user_store=store, email_backend=YourBackend())

SMS delivery

Same pattern, SMS backends — console, Twilio, AWS SNS built in.

warden = AuthWarden(config=config, user_store=store, sms_backend=YourBackend())

Email/SMS copy

Override EmailTemplates / SmsTemplates — subclass and override only the methods you want to change.

warden = AuthWarden(config=config, user_store=store, email_templates=MyTemplates())

Full notification routing logic

If templates and backends aren't enough — say, you want push notifications instead of email/SMS entirely — implement AbstractNotificationService from scratch:

class MyNotificationService:
    async def send_verification_link(self, user, link): ...
    async def send_verification_otp(self, user, otp): ...
    async def send_welcome(self, user): ...
    async def send_password_reset_link(self, user, link): ...
    async def send_password_reset_otp(self, user, otp): ...
    async def send_password_changed(self, user): ...
    async def send_mfa_enabled(self, user): ...
    async def send_mfa_disabled(self, user): ...

warden = AuthWarden(config=config, user_store=store, notification_service=MyNotificationService())

Password hashing

from authwarden.authentication.password import PasswordHandler

warden = AuthWarden(config=config, user_store=store, password_handler=PasswordHandler(config))

Mostly useful if you want to construct it with non-default settings before passing it in — the hasher algorithm itself is chosen via WardenConfig.password_hasher.

Token blacklist (multi-process deployments)

MemoryTokenBlacklist (the default) only works within a single process. For anything horizontally scaled, use Redis:

from authwarden.authentication.jwt import RedisTokenBlacklist

warden = AuthWarden(config=config, user_store=store, token_blacklist=RedisTokenBlacklist(redis_url="redis://..."))

OAuth state storage (multi-process deployments)

Same concern as the token blacklist — MemoryOAuthStateStore doesn't share state across processes. Implement AbstractOAuthStateStore against Redis or your database if you're running more than one process.

warden = AuthWarden(config=config, user_store=store, oauth_state_store=YourStateStore())

Sessions

session_backend is independent of JWT auth — JWTs work with no session backend configured at all. Only set this if you want SessionData records created on login (device/IP fingerprinting, "log out all devices" style features).

config = WardenConfig(secret_key="...", session_backend="redis", redis_url="redis://...")

What's deliberately not customizable today

A few things are fixed by design rather than configurable — noted here so you're not searching for an option that doesn't exist:

  • Transport — tokens are always returned in the JSON response body; there's no built-in cookie transport. See the project roadmap — this is planned post-1.0.
  • Validation strategy — always JWT; database/Redis-backed session-style validation isn't an alternative today, also on the roadmap.
  • SAML / Enterprise OIDC — only consumer OAuth (fixed named providers) is supported currently; per-tenant identity provider configs are on the roadmap.