Skip to content

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.

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.

Enable email verification and set the token expiration via the admin API:

Terminal window
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"
}'
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

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

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.

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.

  • 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.