Register
/api/auth/email/send-verification after sign-in. The user can keep using the app while their email is unverified; gate sensitive flows on User.emailVerified.
Validation rules
| Rule | Enforcement |
|---|---|
Email contains @ | 400 INVALID_EMAIL |
| Email is lowercased + trimmed | Server-side normalization |
| Password ≥ 8 characters | 400 WEAK_PASSWORD |
| Email not already registered | 409 EMAIL_TAKEN |
displayName defaults to the email if omitted.
Log in
From the SDKs
Why Argon2id?
Pylon usesargon2 with the Argon2id variant — winner of the Password Hashing Competition and the OWASP recommendation. It’s resistant to both side-channel attacks (Argon2i) and GPU-based brute-force (Argon2d) by design.
Default parameters:
| Parameter | Value | Why |
|---|---|---|
| Memory cost | 19 MiB | OWASP minimum for interactive logins |
| Time cost | 2 iterations | Balances login latency vs attacker cost |
| Parallelism | 1 | Server-side default |
| Salt | 16 bytes | CSPRNG-generated per password |
Password reset
Pylon doesn’t ship a/api/auth/password/reset endpoint by design — for password reset, use the magic-code flow:
- User clicks “forgot password” → call
/api/auth/magic/send - User enters the emailed code → call
/api/auth/magic/verify - Now they have a valid session — call your custom
setPasswordaction to updateUser.passwordHash
setPassword action looks like:
Configuring the User entity
Password auth expects aUser entity with these fields (auto-created by pylon init):
passwordHash is optional because users who signed up via OAuth or magic code never had one. emailVerified is null until they prove control of the email.
Security notes
- Never deserialize
AuthContextfrom request body. The Rust side intentionally doesn’t deriveDeserializeso a client can’t forgeis_admin: true. Identity comes from the session lookup, not the wire. /api/auth/sessionPOST is gated — only dev mode or admin token can mint a session for an arbitrary user_id. Your registration/login endpoints are the only public ways to obtain a token.- Sessions expire after 30 days by default — see Sessions to change.
- No rate limit on
/loginis built in — add therate_limitplugin if you need brute-force protection at the edge. Cloud applies per-IP rate limiting automatically.
When to use password vs alternatives
Use password when:- Email isn’t reliable (offline-first apps, regions with poor SMTP delivery)
- Compliance requires it
- Users explicitly prefer it