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.

ParamTypeDescription
emailstrUser email (normalized)
passwordstrPlain text password (hashed with argon2)
namestr | NoneDisplay name
avatar_urlstr | NoneProfile image URL
phonestr | NonePhone number
email_verifiedboolMark 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.

ParamTypeDescription
user_idUUIDUser 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.

ParamTypeDescription
emailstrUser email (must match the OTP request)
codestr6-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.

ParamTypeDefaultDescription
user_idUUIDUser ID
rolestrRole name
immediateboolTrueBump 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.

ParamTypeDescription
user_idUUIDUser ID
rolestrRole 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.

ParamTypeDescription
user_idUUIDUser ID
namestr | NoneDisplay name (omit to leave unchanged)
avatar_urlstr | NoneProfile image URL (omit to leave unchanged)
phonestr | NonePhone number (omit to leave unchanged)
email_verifiedboolSet 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, sort_by="created_at", sort_order="desc")

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

List users with pagination and filtering.

ParamTypeDefaultDescription
limitint50Max users per page
offsetint0Number of users to skip
querystr | NoneNoneCase-insensitive partial match on email or name
bannedbool | NoneNoneFilter by banned status
rolestr | NoneNoneFilter by role
sort_bystr"created_at"Sort field — "created_at", "email", or "name"
sort_orderstr"desc""asc" or "desc"

Returns: ListUsersResponse

Get a single user by ID with roles.

ParamTypeDescription
user_idUUIDUser ID

Returns: UserResponse (includes roles) Raises: AuthError if user not found

Delete a user and all related data (roles, tokens, accounts, verification tokens). Fires a user_deleted event.

ParamTypeDescription
user_idUUIDUser ID

Returns: None Raises: ValueError if user not found

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

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

Count users with optional filters. Same filters as list_users().

ParamTypeDefaultDescription
querystr | NoneNoneCase-insensitive partial match on email or name
bannedbool | NoneNoneFilter by banned status
rolestr | NoneNoneFilter 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.

ParamTypeDefaultDescription
user_idUUIDUser ID
active_onlyboolFalseOnly 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.

ParamTypeDefaultDescription
user_idUUIDUser ID
excludeUUID | NoneNoneSession 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.

ParamTypeDescription
user_idUUIDUser ID
providerstrProvider 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).

ParamTypeDescription
rolestr | 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.


PropertyTypeDescription
configAuthFortConfigRead-only access to configuration
session_factoryasync_sessionmakerThe async session factory
hooksHookRegistryThe event hook registry