Skip to content

Server API

AuthFort(
    database_url: str,
    *,
    access_token_ttl: int = 900,
    refresh_token_ttl: int = 2592000,
    jwt_issuer: str = "authfort",
    cookie: CookieConfig | None = None,
    providers: list | None = None,
    key_rotation_ttl: int = 172800,
    introspect_secret: str | None = None,
    allow_signup: bool = True,
    password_reset_ttl: int = 3600,
    rsa_key_size: int = 2048,
    frontend_url: str | None = None,
    email_verify_ttl: int = 86400,
    magic_link_ttl: int = 600,
    email_otp_ttl: int = 300,
    allow_passwordless_signup: bool = False,
    rate_limit: RateLimitConfig | None = None,
    trust_proxy: bool = False,
    trusted_proxies: list[str] | None = None,
)
AuthFort(
    database_url: str,
    *,
    access_token_ttl: int = 900,
    refresh_token_ttl: int = 2592000,
    jwt_issuer: str = "authfort",
    cookie: CookieConfig | None = None,
    providers: list | None = None,
    key_rotation_ttl: int = 172800,
    introspect_secret: str | None = None,
    allow_signup: bool = True,
    password_reset_ttl: int = 3600,
    rsa_key_size: int = 2048,
    frontend_url: str | None = None,
    email_verify_ttl: int = 86400,
    magic_link_ttl: int = 600,
    email_otp_ttl: int = 300,
    allow_passwordless_signup: bool = False,
    rate_limit: RateLimitConfig | None = None,
    trust_proxy: bool = False,
    trusted_proxies: list[str] | None = None,
)

See Configuration for parameter details.


create_user(email, password, *, name=None, avatar_url=None, phone=None, email_verified=False)

Section titled “create_user(email, password, *, name=None, avatar_url=None, phone=None, email_verified=False)”

Create a new user. Works regardless of allow_signup setting.

Param Type Description
email str User email (normalized)
password str Plain text password (hashed with argon2)
name str | None Display name
avatar_url str | None Profile image URL
phone str | None Phone number
email_verified bool Mark email as verified at creation (default False). Fires email_verified event when True.

Returns: AuthResponse Raises: AuthError if email already exists

Authenticate with email and password.

Returns: AuthResponse Raises: AuthError if credentials invalid or user banned

Exchange a refresh token for new tokens.

Returns: AuthResponse Raises: AuthError if token invalid, expired, or revoked

Revoke a refresh token.

Returns: None


Generate a password reset token. Works for all users — including passwordless and OAuth users who want to set their initial password.

Returns: str | None — token string, or None if email not found

Reset password using a reset token. Bumps token version and revokes all refresh tokens.

Returns: boolTrue if successful, False if token invalid/expired

change_password(user_id, old_password, new_password)

Section titled “change_password(user_id, old_password, new_password)”

Change password for an authenticated user. Bumps token version and revokes all refresh tokens.

Returns: None Raises: AuthError if old password is wrong, or if user has no password (code: no_password for passwordless, oauth_account for OAuth)

Set an initial password for a passwordless user (magic link, OTP, or OAuth). Only works when the user has no password set.

Returns: None Raises: AuthError if user already has a password (code: password_already_set) or user not found


Generate an email verification token.

Param Type Description
user_id UUID User ID

Returns: str | None — token string, or None if already verified or user not found

Verify a user’s email using a verification token.

Returns: boolTrue if successful Raises: AuthError if token invalid or expired


Generate a magic link token for passwordless login.

Returns: str | None — token string, or None if email not found (and passwordless signup disabled) or user banned

Verify a magic link token and log the user in. Also sets email_verified=True.

Returns: AuthResponse Raises: AuthError if token invalid/expired or user banned

Generate a 6-digit OTP code for passwordless login.

Returns: str | None — 6-digit code, or None if email not found (and passwordless signup disabled) or user banned

Verify an OTP code and log the user in. Also sets email_verified=True.

Param Type Description
email str User email (must match the OTP request)
code str 6-digit OTP code

Returns: AuthResponse Raises: AuthError if code invalid/expired or user banned


add_role(user_id, role, *, immediate=True)

Section titled “add_role(user_id, role, *, immediate=True)”

Assign a role to a user.

Param Type Default Description
user_id UUID User ID
role str Role name
immediate bool True Bump token version to invalidate existing tokens

Returns: None

remove_role(user_id, role, *, immediate=True)

Section titled “remove_role(user_id, role, *, immediate=True)”

Remove a role from a user.

Returns: None

Get all roles assigned to a user.

Returns: list[str]

Check if a user has a specific role.

Param Type Description
user_id UUID User ID
role str Role name

Returns: bool


Ban a user. Sets banned flag, bumps token version, revokes all refresh tokens.

Returns: None

Unban a user.

Returns: None

update_user(user_id, *, name, avatar_url, phone, email_verified)

Section titled “update_user(user_id, *, name, avatar_url, phone, email_verified)”

Update a user’s profile fields. Only provided fields are changed — omitted fields are left untouched. Pass None to clear a field.

Param Type Description
user_id UUID User ID
name str | None Display name (omit to leave unchanged)
avatar_url str | None Profile image URL (omit to leave unchanged)
phone str | None Phone number (omit to leave unchanged)
email_verified bool Set email verification status (omit to leave unchanged). Fires email_verified event only when transitioning from False to True.

Returns: UserResponse Raises: AuthError if user not found, or if no fields are provided

list_users(*, limit=50, offset=0, query=None, banned=None, role=None, deleted=False, sort_by="created_at", sort_order="desc")

Section titled “list_users(*, limit=50, offset=0, query=None, banned=None, role=None, deleted=False, sort_by="created_at", sort_order="desc")”

List users with pagination and filtering.

Param Type Default Description
limit int 50 Max users per page
offset int 0 Number of users to skip
query str | None None Case-insensitive partial match on email or name
banned bool | None None Filter by banned status
role str | None None Filter by role
deleted bool False If False, exclude anonymized / soft-deleted users; True includes them as well
sort_by str "created_at" Sort field — "created_at", "email", or "name"
sort_order str "desc" "asc" or "desc"

Returns: ListUsersResponse

Get a single user by ID with roles.

Param Type Default Description
user_id UUID User ID
deleted bool False If False, a soft-deleted user is treated as not found; True returns the anonymized record

Returns: UserResponse (includes roles, is_deleted, deleted_at) Raises: AuthError if user not found (or deleted and deleted=False)

Anonymize + soft-delete a user by default: keeps the authfort_users row and its id (so external foreign keys stay valid), scrubs PII, nulls the password, deletes MFA + backup codes, revokes all sessions/refresh tokens, bumps token_version, frees the original email, and sets is_deleted / deleted_at. Idempotent (deleting an already-deleted user is a no-op). Fires a user_deleted event with the original email on the first deletion.

Pass hard=True to remove the row and all related records entirely (legacy behavior — can fail or break referential integrity if your tables reference authfort_users.id without an ON DELETE rule).

Param Type Default Description
user_id UUID User ID
hard bool False True = remove the row entirely instead of anonymizing

Returns: None Raises: ValueError if user not found

get_user_count(*, query=None, banned=None, role=None, deleted=False)

Section titled “get_user_count(*, query=None, banned=None, role=None, deleted=False)”

Count users with optional filters. Same filters as list_users() (excludes soft-deleted users unless deleted=True).

Param Type Default Description
query str | None None Case-insensitive partial match on email or name
banned bool | None None Filter by banned status
role str | None None Filter by role

Returns: int


The session_id is stable across refresh token rotations — it is assigned when a user logs in and stays the same through all subsequent refreshes. The JWT sid claim contains this stable ID. Use it to identify and manage individual sessions (e.g. “sign out other devices”).

get_sessions(user_id, *, active_only=False)

Section titled “get_sessions(user_id, *, active_only=False)”

List sessions for a user. Results are deduplicated by session_id — each entry represents one logical session regardless of how many token rotations have occurred.

Param Type Default Description
user_id UUID User ID
active_only bool False Only return non-revoked, non-expired sessions

Returns: list[SessionResponse]

Revoke a session. Invalidates all refresh tokens in that session’s rotation chain.

Returns: boolTrue if found and revoked

revoke_all_sessions(user_id, *, exclude=None)

Section titled “revoke_all_sessions(user_id, *, exclude=None)”

Revoke all sessions for a user. Bumps token version.

Param Type Default Description
user_id UUID User ID
exclude UUID | None None Session ID to keep alive (e.g. the current session)

Returns: None


Create a new signing key and retire the current one.

Returns: str — new key ID (kid)

Delete expired signing keys from the database.

Returns: int — number of keys deleted

Delete expired verification tokens (password reset, email verify, magic link, OTP).

Returns: int — number of tokens deleted

Delete expired or revoked refresh tokens (sessions).

Returns: int — number of sessions deleted

Get the JWKS (JSON Web Key Set) as a dict. Returns the public signing keys in JWK format. Useful for serving JWKS from non-FastAPI frameworks (Django, Flask, etc.).

Returns: dict — JWKS document with keys array


Get the stored OAuth tokens for a provider account.

Param Type Description
user_id UUID User ID
provider str Provider name (e.g., "google", "github", or any generic provider name)

Returns: dict | None — dict with access_token, refresh_token, and expires_at keys, or None if no account exists for this provider


Decorator to register an event hook.

@auth.on("login")
async def on_login(event):
    ...
@auth.on("login")
async def on_login(event):
    ...

Programmatically register an event hook.


Run pending Alembic migrations programmatically. Prefer the CLI instead: authfort migrate --database-url "...".

Returns: None

Dispose the database engine and connection pool.

Returns: None

Async context manager for database sessions (for non-FastAPI code).

async with auth.get_session() as session:
    ...
async with auth.get_session() as session:
    ...

Returns a FastAPI APIRouter with all auth endpoints (signup, login, logout, refresh, me, password reset, OAuth). Mount with app.include_router(auth.fastapi_router(), prefix="/auth").

Returns: APIRouter

Returns a FastAPI APIRouter serving /.well-known/jwks.json. Mount separately: app.include_router(auth.jwks_router()).

Returns: APIRouter

FastAPI dependency that extracts and verifies the JWT from the request. Returns a UserResponse.

@app.get("/profile")
async def profile(user: UserResponse = Depends(auth.current_user)):
return user

FastAPI dependency factory that checks if the authenticated user has a specific role (or any of a list of roles).

Param Type Description
role str | list[str] Required role(s) — user must have at least one
@app.get("/admin")
async def admin(user=Depends(auth.require_role("admin"))):
...

See FastAPI Integration for full usage guide.


Property Type Description
config AuthFortConfig Read-only access to configuration
session_factory async_sessionmaker The async session factory
hooks HookRegistry The event hook registry