auth.isdocs
Features

Username & password

Email and password is the default credential. When someone signs up on your issuer's login page, auth.is creates a user in that issuer's pool with a password credential — hashed with argon2id, never stored in the clear, never reversible. Everything on this page (signup, verification, reset) is served by the issuer itself; you never build these screens.

Turning signup on

By default a client's login page only lets existing users sign in — there is no "Create account" link. Self-signup requires two flags, both on:

  1. The client's registration_enabled set to true (via create_client / update_client).
  2. The issuer's registrationMode set to open, not invite_only (via update_issuer_settings).

The signup flow

  1. The user submits an email and a password. Passwords must be at least 8 characters — the only complexity rule (length is the honest signal; the rest is theatre).
  2. auth.is creates an unverified user and its argon2id password credential, then emails a short verification code to the address.
  3. The verify screen takes the code. A correct code marks the email verified and the account is usable.

Email verification matters beyond hygiene: the account-linking rule only auto-links a federated login to a password account when both the local email and the upstream email are verified. An unverified account never gets silently claimed.

Enumeration parity — a feature, not an accident

auth.is deliberately refuses to tell an anonymous visitor whether an email already has an account. Every user-facing surface is built to leak nothing:

  • Login returns a single generic failure. "Wrong password", "no such user", "no password set", and "rate limited" all produce the identical result with no reason code. A miss even burns the same argon2 work as a hit (verifying against a dummy hash), so there is no timing oracle either.
  • Signup for an existing address does not error. It performs the same argon2 work, shows the same verify screen, and emails a "you already have an account" notice instead of a code — so the flow is indistinguishable from a fresh signup, but can never be completed (no usable code is issued).
  • Password reset for an unknown address behaves the same way: same screen, a "no account here" notice instead of a code, no completable path.

Password endpoints are also rate-limited on two dimensions at once — per (issuer, email) and per IP — so credential stuffing is throttled before it reaches argon2. Login allows 5 attempts per email per 15 minutes (and 30 per IP); signup, verify, and reset have their own buckets, and a code resend has a 60-second cooldown.

Password reset

The "forgot password" flow mirrors signup: request a reset for your email, receive a code (or the silent decoy for an unknown address), and set a new password of at least 8 characters.

What a password login yields

A password login produces exactly the same tokens as any other login — the credential type is invisible to your application. You get an ID token carrying the claims the granted scopes allow (sub, and email / email_verified / profile fields), with email_verified reflecting whether the account completed verification. See Scopes & claims for the full map.

Next steps