Skip to content

Architecture

FastAuth is organized in four layers. Knowing them helps you understand which object to customize.

flowchart LR
    subgraph Your app
        APP[FastAPI app]
        ROUTES["Your routes<br/>Depends(require_auth)"]
    end
    subgraph FastAuth
        CONFIG[FastAuthConfig]
        FA[FastAuth instance]
        ROUTER["api/router.py<br/>/auth/* routes"]
        DEPS["api/deps.py<br/>require_auth / require_role"]
        CORE["core/<br/>tokens, oauth, rbac, emails, jwks"]
        PROV["providers/<br/>Credentials, Google, GitHub,<br/>MagicLinks, Passkey"]
    end
    subgraph Your DB
        ADAPTER["adapters/<br/>SQLAlchemy | Memory | Custom"]
    end
    CONFIG --> FA
    FA --> ROUTER
    FA --> DEPS
    ROUTER --> CORE
    ROUTER --> PROV
    CORE --> ADAPTER
    FA -. role_adapter / session_adapter .-> ADAPTER
    APP -->|auth.mount| ROUTER
    APP --> ROUTES
    ROUTES --> DEPS
    DEPS --> CORE

Layers

  1. Config (fastauth.config): FastAuthConfig, JWTConfig, PasswordConfig, SecurityConfig. Validated on construction.
  2. FastAuth instance (fastauth.app): holds config, jwks_manager, email_dispatcher, and the post-construction role_adapter / session_adapter handles. mount(app) wires the routes.
  3. Routing + dependencies (fastauth.api): the /auth/* routes and the require_auth / require_role / require_permission FastAPI dependencies your app consumes.
  4. Providers, core, adapters (fastauth.providers, fastauth.core, fastauth.adapters): providers know how to authenticate a user (credentials, OAuth, magic link, passkey); core implements JWT, OAuth flow, RBAC, email dispatch, JWKS; adapters persist users/tokens/sessions/roles/oauth/passkeys.

How a request flows

  • POST /auth/login → router → CredentialsProvider.authenticate(adapter, email, password, token_adapter, security, client_ip) → returns UserData → router issues a JWT pair via core.tokens.async_create_token_pair → if token_adapter set, the refresh JTI is stored → if token_delivery="cookie", cookies are set on the response.
  • GET /your/route with Depends(require_auth)api.deps.get_current_user reads token from header or cookie, decodes via core.tokens.decode_token, loads the user via adapter.get_user_by_id → if token came from a cookie and the method is unsafe (POST/PUT/PATCH/DELETE), enforce_cookie_csrf validates the X-CSRF-Token header against the csrf_token cookie.

Design rules

  • Core is DB-agnostic. Business logic lives in core/ and api/; adapters/ only persists and reads.
  • Adapters are protocols. UserAdapter, TokenAdapter, SessionAdapter, RoleAdapter, OAuthAccountAdapter, PasskeyAdapter are typing.Protocols in fastauth.core.protocols. Implement any of them; FastAuth doesn't care.
  • Assign role_adapter / session_adapter after construction. Unlike adapter and token_adapter (which go in FastAuthConfig), these are assigned after FastAuth(config) because the /auth/sessions and /auth/roles endpoints return 400 "… not configured" until you do. See RBAC and Tokens & sessions.