Factors Reference¶
PasswordFactor¶
Module: neozen.core.factors.password
Protocol: AuthenticatingFactorProtocol
from neozen.core.factors.password import PasswordFactor, create_password_factor
# Generic (type-safe with NeoZen models)
factor = PasswordFactor(identifier, subject_storage, hasher)
# Non-generic (for custom models)
factor = create_password_factor(identifier, subject_storage, hasher)
Methods¶
| Method | Description |
|---|---|
authenticate(payload) |
Verify {"identifier": ..., "password": ...} |
enroll(subject, payload) |
Set initial password |
change_password(subject, old, new) |
Change password (verifies old) |
Exceptions¶
InvalidCredentialsError-- wrong password or user not foundPasswordFactorError-- base exception for password errors
Security¶
- Timing-safe comparison via
hmac.compare_digest - Dummy hash on user-not-found to prevent timing attacks
- Automatic hash upgrade on successful login
MagicLinkFactor¶
Module: neozen.core.factors.magic_link
Protocol: ChallengingFactorProtocol
from neozen.core.factors.magic_link import MagicLinkFactor, MagicLinkConfig
factor = MagicLinkFactor(
config=MagicLinkConfig(link_base_url="https://app.com/verify"),
token_repository=token_repo,
subject_email_lookup=email_lookup,
email_sender=email_sender,
token_hash_key="secret",
)
Methods¶
| Method | Description |
|---|---|
begin_authentication(subject_id) |
Generate token, send email |
complete_authentication(subject_id, response=token) |
Verify token |
is_enrolled(subject_id) |
True if subject has an email |
Required Protocols¶
MagicLinkTokenRepository--create,get_by_hash,mark_used,count_pending,invalidate_allSubjectEmailLookup--get_email(subject_id),subject_exists(subject_id)EmailSenderProtocol--send(EmailMessage)
TOTPFactor¶
Module: neozen.core.factors.totp
Protocols: EnrollableFactorProtocol
from neozen.core.factors.totp import TOTPFactor, TOTPConfig
factor = TOTPFactor(
config=TOTPConfig(issuer="My App"),
subject_repository=repo,
backup_code_repository=backup_repo,
hasher=password_hasher,
)
Methods¶
| Method | Description |
|---|---|
begin_enrollment(subject, account_name) |
Generate secret + QR code |
confirm_enrollment(subject, code) |
Verify code and enable TOTP |
authenticate(subject, code) |
Verify TOTP or backup code |
unenroll(subject) |
Disable TOTP |
Dependencies¶
Requires pyotp (uv add "neozen[totp]"). QR data URIs also need qrcode, which is optional.
WebAuthnFactor¶
Module: neozen.core.factors.webauthn
Protocols: EnrollableFactorProtocol + ChallengingFactorProtocol
from neozen.core.factors.webauthn import WebAuthnFactor, WebAuthnConfig
factor = WebAuthnFactor(
config=WebAuthnConfig(
rp_id="localhost",
rp_name="My App",
origin="http://localhost:8000",
),
credential_repository=cred_repo,
challenge_repository=challenge_repo,
)
Methods¶
| Method | Description |
|---|---|
begin_registration(subject_id) |
Generate registration options |
complete_registration(subject_id, credential) |
Store credential |
begin_authentication(subject_id) |
Generate authentication challenge |
complete_authentication(subject_id, response) |
Verify assertion |
Dependencies¶
Requires py-webauthn (uv add "neozen[webauthn]").