Email Verification
When require_email_verification is enabled, users must verify their email address before they can complete the OAuth2 login flow. Unverified users are shown a verification page after login instead of receiving an authorization code. Passkey signup and both username-based and discoverable passkey login follow this policy. Signup requires an email address even when the email profile field is hidden or optional.
Verification flow
Section titled “Verification flow”sequenceDiagram
actor User
participant Browser
participant IdP as Autentico
participant Email as SMTP Server
User->>Browser: Sign up or log in
Browser->>IdP: POST /oauth2/login
IdP->>IdP: Credentials valid, email not verified
IdP->>Browser: Render verify_email page (mode: blocked)
IdP->>Email: Send verification link
Email->>User: Email with verification URL
User->>Browser: Click verification link
Browser->>IdP: GET /oauth2/verify-email?token=...
IdP->>IdP: Validate token, mark email verified
IdP->>Browser: 302 -> redirect_uri?code=AUTH_CODE
The verification link contains a cryptographically random token (32 bytes, base64url-encoded). Only the SHA-256 hash of the token is stored in the database, so a database compromise does not expose valid verification links.
Configuration
Section titled “Configuration”Enable email verification and set the token expiration via the admin API:
curl -X PUT https://auth.example.com/admin/api/settings \ -H "Authorization: Bearer $ADMIN_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "require_email_verification": "true", "email_verification_expiration": "24h" }'Settings
Section titled “Settings”| Setting | Default | Description |
|---|---|---|
require_email_verification |
false |
When true, unverified users cannot complete login |
email_verification_expiration |
24h |
How long a verification link remains valid |
SMTP requirements
Section titled “SMTP requirements”Email verification requires a working SMTP configuration. Set these settings via the admin API or Admin UI:
| Setting | Description |
|---|---|
smtp_host |
SMTP server hostname |
smtp_port |
SMTP server port (typically 587) |
smtp_username |
SMTP authentication username |
smtp_password |
SMTP authentication password |
smtp_from |
Sender email address |
Endpoints
Section titled “Endpoints”Verify email
Section titled “Verify email”GET {oauth_path}/verify-email?token=...&client_id=...&redirect_uri=...&scope=...&state=...
Validates the verification token and, if valid, marks the user’s email as verified, creates an IdP session, issues an authorization code, and redirects to the client. The OAuth2 parameters are carried through the verification link so the login flow resumes seamlessly.
If the token is expired or invalid, the user is shown the verification page in “expired” mode with an option to request a new link.
Resend verification
Section titled “Resend verification”POST {oauth_path}/resend-verification
Generates a new verification token and sends a fresh verification email. Accepts form-encoded parameters:
| Parameter | Description |
|---|---|
username |
The user’s username |
redirect_uri |
OAuth2 redirect URI (carried through) |
state |
OAuth2 state parameter (carried through) |
client_id |
OAuth2 client ID (carried through) |
scope |
OAuth2 scope (carried through) |
code_challenge, code_challenge_method |
PKCE parameters; required for public clients |
authorize_sig |
Signature from the authorization or magic-link form; required |
Requests must carry a valid authorization signature and pass the current client, redirect URI, scope and PKCE checks before a new verification token is stored or emailed. Invalid authorization requests return HTTP 400. For accepted requests, the same generic sent page is returned for unknown, inactive, unverified or already verified accounts, including accounts with no email address. Token-storage and SMTP failures do not change this public response. Eligible accounts receive a fresh link; SMTP delivery runs in the background after the token is stored, and delivery failures are logged on the server. Up to eight verification resends can be in flight per process. If capacity is full or SMTP is not configured, the response stays generic and the existing verification link is preserved; retry later. SMTP connection setup and each SMTP operation have a fixed 30-second timeout for all outgoing email. STARTTLS keeps certificate and host verification enabled; configured SMTP authentication requires the server to advertise AUTH.
Security considerations
Section titled “Security considerations”- Token hashing – only the SHA-256 hash of the token is stored; the raw token exists only in the email link
- Single-use – once verified, the token cannot be reused
- Expiration – tokens expire after the configured duration (default: 24 hours)
- Parameter integrity – OAuth2 parameters in the verification link are protected by an HMAC signature (
authorize_sig) to prevent tampering. A signature does not replace authorization: the server also revalidates the active client, registered callback, allowed scopes, code-flow permission and PKCE before sending or redeeming a link. Invalid authorization leaves the verification token unchanged. - Resend privacy – accepted requests use one generic response and the same randomized-delay policy across account states. SMTP delivery does not block the response.