Skip to content

Credentials provider

Email/password authentication with Argon2 hashing and brute-force lockout.

from fastauth.providers.credentials import CredentialsProvider

provider = CredentialsProvider()                                   # default
provider = CredentialsProvider(max_login_attempts=10, lockout_duration=600)

Constructor args control the fallback lockout thresholds, but FastAuthConfig.security (SecurityConfig) takes precedence when both are set.

Endpoints

Method Path Request Response
POST /auth/register {email, password, name?} 201 TokenResponse (JSON) or MessageResponse (cookie); 409 if email exists
POST /auth/login {email, password, remember=false} TokenResponse or MessageResponse; 401 on bad credentials
POST /auth/logout {message} (requires auth)

Password hashing

hash_password and verify_password use Argon2 (argon2-cffi). Passwords are validated against FastAuthConfig.password on /auth/register and /auth/reset-password; failure returns 400 with the validation message.

Account lockout

CredentialsProvider.authenticate throttles by email (always) and optionally by client IP (security.login_attempts_by_ip=True). When failures exceed security.max_login_attempts (default 5), the account key is locked for security.lockout_duration (default 300s). Further login attempts during lockout raise AccountLockedError carrying the remaining seconds. State is persisted via token_adapter (type "login_attempt"); without one, in-process memory is used (non-production fallback controlled by security.use_memory_login_attempts_without_token_adapter).

Hooks

  • on_signup — fires on /auth/register.
  • on_signin — fires on successful /auth/login (provider="credentials").
  • on_signout — fires on /auth/logout.

allow_signin is NOT called on /auth/login. It is only invoked by OAuth, magic-link, and passkey. If you need to gate credentials login (e.g. on email_verified), do it in your own route wrapper.

Email verification

Registration does not send a verification email. The user must explicitly call POST /auth/request-verify-email. See Email verification.

Common mistakes

  • 400 Credentials provider is not configured on /auth/register — remove a stray CredentialsProvider from the providers list, or add it back.
  • 401 Invalid email or password on a freshly registered user — you sent password from the request body but the password field is hashed; retype the original password.
  • Lockout persists after you fix the buglogin_attempt records have a 15-minute TTL between lockouts. Clear via token_adapter.delete_user_tokens(user_id, "login_attempt").