Authentication Notifications Setup Guide¶
This guide explains how to set up email notifications when users create accounts and log in to your application.
Overview¶
The system sends email notifications to an admin email address when: - A new user signs up (account creation) - A user logs in (authentication)
Prerequisites¶
- SMTP Email Account: You need an SMTP-enabled email account (Gmail, SendGrid, Mailgun, etc.)
- Admin Email Address: The email address where you want to receive notifications
- Backend API: Your FastAPI backend must be accessible via HTTPS (for production webhooks)
Configuration¶
1. Environment Variables¶
Add these environment variables to your backend/.env file:
# Email Notification Settings
EMAIL_NOTIFICATIONS_ENABLED=true
ADMIN_EMAIL=your-admin@example.com
# SMTP Configuration (Gmail example)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-specific-password
SMTP_FROM_EMAIL=your-email@gmail.com
# Optional: Webhook Secret for Security (recommended in production)
SUPABASE_WEBHOOK_SECRET=your-random-secret-string
Gmail Setup (Example)¶
If using Gmail:
1. Enable 2-Factor Authentication on your Google account
2. Generate an App Password
3. Use the app password (not your regular password) as SMTP_PASSWORD
Other SMTP Providers¶
SendGrid:
Mailgun:
SMTP_HOST=smtp.mailgun.org
SMTP_PORT=587
SMTP_USER=your-mailgun-username
SMTP_PASSWORD=your-mailgun-password
AWS SES:
SMTP_HOST=email-smtp.us-east-1.amazonaws.com
SMTP_PORT=587
SMTP_USER=your-aws-access-key
SMTP_PASSWORD=your-aws-secret-key
2. Supabase Webhook Configuration¶
Supabase webhooks can notify your backend when auth events occur. There are two methods:
Method 1: Database Webhooks (For Signups - Recommended)¶
This method works well for tracking user signups:
- Go to Supabase Dashboard → Your Project → Database → Webhooks
- Click "Create a new webhook"
- Configure:
- Name:
User Signup Notifications - Table:
auth.users - Events: Select
INSERT(for new signups) - HTTP Request:
- URL:
https://yourdomain.com/api/webhooks/auth - Method:
POST - HTTP Request headers:
- (Optional) Add header:
x-supabase-signature: your-webhook-secret(use same value asSUPABASE_WEBHOOK_SECRET)
- URL:
- Click "Create webhook"
Note: Database webhooks only trigger on database changes. They work great for signups (INSERT events) but won't capture every login unless you set up additional triggers.
Method 2: Edge Function + Webhook (For Signups AND Logins)¶
For comprehensive tracking of both signups and logins, use a Supabase Edge Function:
- Create Edge Function in Supabase Dashboard → Edge Functions
- Create a new function called
auth-webhook-forwarder:
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
const WEBHOOK_URL = Deno.env.get('WEBHOOK_URL') || 'https://yourdomain.com/api/webhooks/auth/events'
serve(async (req) => {
try {
const { event, user } = await req.json()
// Forward to your backend webhook
const response = await fetch(WEBHOOK_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
event: event,
user: user,
timestamp: new Date().toISOString()
})
})
return new Response(
JSON.stringify({ success: true, status: response.status }),
{ headers: { "Content-Type": "application/json" } }
)
} catch (error) {
return new Response(
JSON.stringify({ error: error.message }),
{ status: 500, headers: { "Content-Type": "application/json" } }
)
}
})
- Set environment variable in Edge Function settings:
-
WEBHOOK_URL:https://yourdomain.com/api/webhooks/auth/events -
Create Database Trigger to call the Edge Function:
Go to SQL Editor in Supabase and run:
-- Function to call Edge Function on auth events
CREATE OR REPLACE FUNCTION notify_auth_events()
RETURNS TRIGGER AS $$
DECLARE
payload json;
BEGIN
-- For INSERT (signup)
IF TG_OP = 'INSERT' THEN
payload = json_build_object(
'event', 'SIGNED_UP',
'user', row_to_json(NEW),
'timestamp', NOW()
);
END IF;
-- For UPDATE (could be login if last_sign_in_at changed)
IF TG_OP = 'UPDATE' AND OLD.last_sign_in_at IS DISTINCT FROM NEW.last_sign_in_at THEN
payload = json_build_object(
'event', 'SIGNED_IN',
'user', row_to_json(NEW),
'timestamp', NOW()
);
END IF;
-- Call Edge Function
PERFORM net.http_post(
url := 'https://your-project-ref.supabase.co/functions/v1/auth-webhook-forwarder',
headers := jsonb_build_object(
'Content-Type', 'application/json',
'Authorization', 'Bearer ' || current_setting('app.settings.service_role_key', true)
),
body := payload::text
);
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- Create trigger on auth.users table
CREATE TRIGGER auth_users_webhook_trigger
AFTER INSERT OR UPDATE ON auth.users
FOR EACH ROW
EXECUTE FUNCTION notify_auth_events();
Note: This method requires the pg_net extension and service role key configuration. It's more complex but provides comprehensive tracking.
Method 3: Simple Database Webhook (Easiest - Signups Only)¶
The simplest approach is to just set up a database webhook for signups (Method 1), which covers the most important use case. Logins can be tracked separately if needed using analytics tools.
Testing¶
Test Email Service Locally¶
You can test the email service directly:
# In Python shell or script
from services.email_service import email_service
# Test signup notification
email_service.notify_user_signup(
email="test@example.com",
user_id="test-user-id",
provider="google",
created_at="2025-01-01T00:00:00Z"
)
# Test login notification
email_service.notify_user_login(
email="test@example.com",
user_id="test-user-id",
provider="google",
login_time="2025-01-01T00:00:00Z"
)
Test Webhook Endpoint¶
You can test the webhook endpoint using curl:
# Test signup webhook
curl -X POST https://yourdomain.com/api/webhooks/auth \
-H "Content-Type: application/json" \
-d '{
"type": "INSERT",
"table": "auth.users",
"record": {
"id": "test-user-id",
"email": "test@example.com",
"created_at": "2025-01-01T00:00:00Z",
"identities": [{"provider": "google"}]
}
}'
# Test auth events webhook
curl -X POST https://yourdomain.com/api/webhooks/auth/events \
-H "Content-Type: application/json" \
-d '{
"event": "SIGNED_UP",
"user": {
"id": "test-user-id",
"email": "test@example.com"
},
"timestamp": "2025-01-01T00:00:00Z"
}'
Troubleshooting¶
Email Notifications Not Sending¶
- Check logs: Look for email service initialization messages in backend logs
- Verify SMTP credentials: Ensure SMTP_USER and SMTP_PASSWORD are correct
- Check ADMIN_EMAIL: Ensure it's set correctly
- Test SMTP connection: Try sending a test email manually
- Gmail users: Make sure you're using an App Password, not your regular password
Webhooks Not Receiving Events¶
- Check webhook URL: Ensure it's accessible (use HTTPS in production)
- Verify Supabase webhook configuration: Check that the webhook is active in Supabase dashboard
- Check webhook logs: Supabase shows webhook delivery status in the dashboard
- Verify table name: Must be exactly
auth.users(case-sensitive) - Check backend logs: Look for webhook receipt messages
Common Issues¶
"ADMIN_EMAIL not set": Set the ADMIN_EMAIL environment variable
"SMTP credentials not configured": Set SMTP_USER and SMTP_PASSWORD
"Email notifications disabled": Set EMAIL_NOTIFICATIONS_ENABLED=true
Gmail authentication errors: Use an App Password, not your regular password
Webhook signature mismatch: Ensure SUPABASE_WEBHOOK_SECRET matches the header value in Supabase webhook config
Security Notes¶
- Webhook Secret: Always use a webhook secret in production to verify requests are from Supabase
- HTTPS Only: Use HTTPS for webhook URLs in production (required for Supabase webhooks)
- SMTP Security: Use TLS/STARTTLS (port 587) for SMTP connections
- Environment Variables: Never commit credentials to version control (use .env file which is gitignored)
Production Deployment¶
When deploying to production:
- Set all environment variables in your hosting platform (Render, Railway, etc.)
- Ensure your backend URL is accessible via HTTPS
- Update webhook URLs in Supabase to use your production domain
- Test notifications after deployment
- Monitor logs for any email delivery issues
Disabling Notifications¶
To disable email notifications without removing the code:
This will skip sending emails but keep the webhook endpoints active.