Auth & Verification Troubleshooting Guide

Issue: “Email not confirmed”

Users may encounter the “Email not confirmed” error even if they believe they have verified their account. This document explains why this happens and how to resolve it.

Source of Truth

Authentication status is managed by Supabase Auth (auth.users table), which is separate from the application’s public.profiles table.

  • auth.users: Contains the secure email_confirmed_at timestamp. This is the only field that determines if a user can login when “Confirm Email” is enabled.
  • public.profiles: Contains a mirror is_email_verified flag, but this is for display purposes only and does not control login access.

Common Causes for Mismatch

  1. Phone Verification Only: A user verified their phone number but not their email. If the login requires email/password, email verification is strictly enforced.
  2. Stale Link: The user clicked an expired verification link.
  3. Different Email: The user verified email A but is trying to login with email B.
  4. Email Change: The user requested an email change. Until the new email is verified, the account might be locked or require verification of the new address.

Solutions

For Users

  1. Check Spam Folder: Look for the verification email from Flow.
  2. Resend Verification: Use the “Invia nuovamente email di verifica” link that appears on the login screen when this error occurs.
  3. Verify Correct Email: Ensure you are logging in with the exact email address you verified.

For Admins (Manual Verification)

If a user is stuck, you can manually confirm them via the Supabase Dashboard:

  1. Go to Authentication > Users.
  2. Find the user by email.
  3. Click the three dots icon > Confirm User (or “Verify Email”).
  4. This updates auth.users.email_confirmed_at immediately.

Debugging

To verify a user’s status programmatically, you need the SERVICE_ROLE_KEY. With it, you can run:

const { data: { users } } = await supabase.auth.admin.listUsers();
const user = users.find(u => u.email === 'user@example.com');
console.log(user.email_confirmed_at); // If null, user is NOT verified.