Skip to content

Password Management

AuthFort provides password reset (forgot password), change password (authenticated), and set password (for passwordless users) flows. All are programmatic — you control how to deliver reset tokens (email, SMS, etc.).

The password reset flow has three steps:

  1. Generate a reset token

    token = await auth.create_password_reset_token("user@example.com")
    token = await auth.create_password_reset_token("user@example.com")

    Returns a random token string, or None if the email doesn’t exist. The None return prevents user enumeration — your API should return the same response regardless. Works for all users — including passwordless (magic link, OTP) and OAuth users who want to set their initial password.

  2. Deliver the token

    You handle delivery. AuthFort doesn’t send emails.

    token = await auth.create_password_reset_token(email)
    if token:
        await send_email(
            to=email,
            subject="Reset your password",
            body=f"https://myapp.com/reset?token={token}",
        )
    # Always return success to prevent enumeration
    token = await auth.create_password_reset_token(email)
    if token:
        await send_email(
            to=email,
            subject="Reset your password",
            body=f"https://myapp.com/reset?token={token}",
        )
    # Always return success to prevent enumeration
  3. Reset the password

    success = await auth.reset_password(token, new_password)
    # True if reset, False if invalid/expired token
    success = await auth.reset_password(token, new_password)
    # True if reset, False if invalid/expired token

Reset tokens are single-use and expire after password_reset_ttl seconds (default: 1 hour). After a successful reset, the user’s token_version is bumped, invalidating all existing tokens, and all refresh tokens are revoked.

For authenticated users who know their current password:

await auth.change_password(user_id, old_password, new_password)
# Raises AuthError if old password is wrong
await auth.change_password(user_id, old_password, new_password)
# Raises AuthError if old password is wrong

This verifies the old password, hashes the new one, bumps the token version, and revokes all refresh tokens.

Users who signed up via magic link, OTP, or OAuth have no password. They can set one to enable email/password login:

await auth.set_password(user_id, new_password)
# Raises AuthError if user already has a password
await auth.set_password(user_id, new_password)
# Raises AuthError if user already has a password

Or via the built-in REST endpoint (requires authentication):

POST /auth/set-password
Authorization: Bearer <access_token>
Content-Type: application/json

{"password": "newpassword123"}
POST /auth/set-password
Authorization: Bearer <access_token>
Content-Type: application/json

{"password": "newpassword123"}

This only works when the user has no password set. If they already have one, use change_password instead.

Emits password_reset_requested, password_reset, password_changed, and password_set events. See Events & Hooks for all events and their payloads.