Skip to main content

Native async auth for Quart

Project description

quart-security

quart-security is a native async authentication extension for Quart.

It is designed as a practical replacement path for Flask-Security style session auth in Quart applications, without Flask shims and without Flask-Login.

What You Get

Core auth

  • Session-based login and logout
  • Email/password registration
  • Password change flow (including OAuth-style users that don’t know an initial random password)
  • current_user proxy
  • @auth_required("session") and @roles_required(...)

MFA

  • TOTP setup and verification
  • Recovery code generation and one-time consumption

WebAuthn (passkeys / security keys)

  • Credential registration
  • Passwordless sign-in (first factor)
  • Authenticated verification flow (step-up / second factor)
  • Credential deletion

Extension and compatibility surface

  • Quart extension pattern (Security(app, datastore))
  • Flask-Security-style endpoint naming through url_for_security()
  • Signals for auth lifecycle events
  • Overridable templates under templates/security/
  • Datastore hooks can be implemented as async methods or simple sync methods

Non-Goals (Current Scope)

This project intentionally focuses on session auth and MFA currently in active use:

  • No token-based API auth
  • No SMS/email OTP
  • No account locking workflow
  • No remember-me token system

Installation

Install from repository

uv add git+https://github.com/level09/quart-security.git

Local development

uv sync --group dev
uv run pytest -q

Package build backend: flit.

Quick Integration

from quart import Quart
from quart_security import Security, SQLAlchemyUserDatastore

# your models should include fields used by auth, roles, and MFA/WebAuthn
from myapp.models import db, User, Role, WebAuthnCredential


def create_app():
    app = Quart(__name__)

    app.config.update(
        SECRET_KEY="change-me",
        SECURITY_PASSWORD_SALT="change-me-too",
        SECURITY_POST_LOGIN_VIEW="/dashboard",
        SECURITY_POST_REGISTER_VIEW="/login",
    )

    db.init_app(app)
    datastore = SQLAlchemyUserDatastore(
        db,
        User,
        Role,
        webauthn_model=WebAuthnCredential,
    )

    Security(app, datastore)
    return app

Required Model Surface

Your user/role models are expected to provide the fields used by active features.

Minimum practical user fields:

  • fs_uniquifier
  • email
  • password
  • active
  • roles

For tracking / MFA / WebAuthn features:

  • last_login_at, current_login_at, last_login_ip, current_login_ip, login_count
  • tf_primary_method, tf_totp_secret, mf_recovery_codes
  • fs_webauthn_user_handle
  • relationship/association for stored WebAuthn credentials

Optional for lockout support:

  • failed_login_count
  • locked_until

Key Configuration

The extension uses SECURITY_* keys for migration-friendly configuration.

Core:

  • SECURITY_PASSWORD_HASH (default: argon2 / argon2id; set to pbkdf2_sha512 to keep old behavior)
  • SECURITY_PASSWORD_SALT (recommended)
  • SECURITY_PASSWORD_LENGTH_MIN (default: 12)
  • SECURITY_PASSWORD_BREACH_CHECK (default: True) - HIBP k-anonymity check on register/change
  • SECURITY_PASSWORD_BREACH_COUNT_MIN (default: 1) - minimum breach count to reject
  • SECURITY_ARGON2_MEMORY_COST / SECURITY_ARGON2_TIME_COST / SECURITY_ARGON2_PARALLELISM - override argon2 params (production defaults: 19456/2/1)
  • SECURITY_LOGIN_MAX_ATTEMPTS (default: 5)
  • SECURITY_LOCKOUT_MINUTES (default: 15)
  • SECURITY_REGISTERABLE
  • SECURITY_CHANGEABLE
  • SECURITY_TRACKABLE
  • SECURITY_CSRF_PROTECT (default: True)

Existing pbkdf2_sha512 and bcrypt hashes continue to verify after the argon2 default change. They are transparently rehashed to argon2id on the user's next successful login.

2FA:

  • SECURITY_TWO_FACTOR
  • SECURITY_TOTP_ISSUER
  • SECURITY_MULTI_FACTOR_RECOVERY_CODES
  • SECURITY_MULTI_FACTOR_RECOVERY_CODES_N

WebAuthn:

  • SECURITY_WEBAUTHN
  • SECURITY_WAN_ALLOW_AS_FIRST_FACTOR
  • SECURITY_WAN_ALLOW_AS_MULTI_FACTOR
  • SECURITY_WAN_RP_ID (optional override)
  • SECURITY_WAN_RP_NAME (optional override)
  • SECURITY_WAN_EXPECTED_ORIGIN (optional override)
  • SECURITY_WAN_REQUIRE_USER_VERIFICATION (default: True)

Routing:

  • SECURITY_POST_LOGIN_VIEW
  • SECURITY_POST_REGISTER_VIEW

Route Map

Core:

  • /login
  • /register
  • /logout
  • /change

2FA:

  • /tf-setup
  • /tf-validate
  • /tf-select
  • /mf-recovery-codes
  • /mf-recovery

WebAuthn:

  • /wan-register
  • /wan-register-response
  • /wan-signin
  • /wan-signin-response
  • /wan-verify
  • /wan-verify-response
  • /wan-delete

Template Overrides

Default templates are intentionally simple and framework-neutral.

Override by placing templates with the same names under your app’s templates/security/ directory.

Public API

from quart_security import (
    Security,
    SQLAlchemyUserDatastore,
    current_user,
    auth_required,
    roles_required,
    UserMixin,
    RoleMixin,
    hash_password,
    verify_password,
    user_authenticated,
    user_logged_out,
    password_changed,
    tf_profile_changed,
    user_registered,
    url_for_security,
)

Testing

Project tests cover:

  • password hashing/validation
  • auth and role decorators
  • register/login/logout/change-password
  • TOTP and recovery code flows
  • WebAuthn register/sign-in/verify/delete route behavior

Run:

uv run pytest -q

WebAuthn staging validation (recommended before release tags)

Run this in a HTTPS staging environment with production-like hostnames and real browser prompts:

  1. Register a passkey from /wan-register and verify it is persisted with expected name, usage, and sign_count.
  2. Complete passwordless sign-in from /wan-signin with the same credential.
  3. Complete authenticated verify flow from /wan-verify while already signed in.
  4. Delete credential from /wan-delete and confirm subsequent passkey auth fails for that credential.
  5. Repeat step 1 and step 2 with a second authenticator type (for example platform passkey + hardware key) to validate device portability assumptions.

Notes for Production

  • Run behind HTTPS for WebAuthn in non-local environments.
  • Set explicit WebAuthn RP values (SECURITY_WAN_RP_ID, SECURITY_WAN_EXPECTED_ORIGIN) when behind proxies or multiple domains.
  • Keep CSRF protection enabled unless you have a deliberate replacement.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

quart_security-1.4.0.tar.gz (26.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

quart_security-1.4.0-py3-none-any.whl (34.1 kB view details)

Uploaded Python 3

File details

Details for the file quart_security-1.4.0.tar.gz.

File metadata

  • Download URL: quart_security-1.4.0.tar.gz
  • Upload date:
  • Size: 26.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for quart_security-1.4.0.tar.gz
Algorithm Hash digest
SHA256 8f57942272db2399b9956b7b603b46bacab3ec731599c3b65c0dac620d97ca07
MD5 3601ef96703ade5b4b71eb3913078170
BLAKE2b-256 8895a6f979dd8df59629b691d22db56091e43bdfab952d86a1135117dac16a17

See more details on using hashes here.

Provenance

The following attestation bundles were made for quart_security-1.4.0.tar.gz:

Publisher: publish.yml on level09/quart-security

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file quart_security-1.4.0-py3-none-any.whl.

File metadata

  • Download URL: quart_security-1.4.0-py3-none-any.whl
  • Upload date:
  • Size: 34.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for quart_security-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 42846cf9f1af9c4a86d100c9bdd199c095eecfed288ded5cbf8f3cbd63421811
MD5 7d08d69b14203f5dccb49d63c779e024
BLAKE2b-256 d0e5ee6c92607ae99bdb64b56cba63baa1a6738ca5e39ddc43e25d72205d758e

See more details on using hashes here.

Provenance

The following attestation bundles were made for quart_security-1.4.0-py3-none-any.whl:

Publisher: publish.yml on level09/quart-security

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page