supabase-email-auth
This skill should be used when implementing Supabase email/password authentication in Next.js applications. Automates the complete setup including client/server utilities, login/register pages, auth callback handling, middleware protection, and email configuration. Handles common errors like PKCE flow issues, cookie management, and admin role verification.
SKILL.md
| Name | supabase-email-auth |
| Description | This skill should be used when implementing Supabase email/password authentication in Next.js applications. Automates the complete setup including client/server utilities, login/register pages, auth callback handling, middleware protection, and email configuration. Handles common errors like PKCE flow issues, cookie management, and admin role verification. |
name: supabase-email-auth description: This skill should be used when implementing Supabase email/password authentication in Next.js applications. Automates the complete setup including client/server utilities, login/register pages, auth callback handling, middleware protection, and email configuration. Handles common errors like PKCE flow issues, cookie management, and admin role verification.
Supabase Email Authentication Setup Skill
Purpose
This skill provides a complete, production-ready implementation of Supabase email/password authentication for Next.js 13+ applications using the App Router. It eliminates the repetitive 1-hour setup process and resolves common authentication errors by providing tested, working code patterns.
The skill includes:
- Client and server-side authentication utilities
- Login and registration pages with proper UI/UX
- OAuth callback handling with PKCE flow
- Password reset functionality
- Admin role-based access control
- Environment variable configuration
- Middleware for route protection
When to Use This Skill
Use this skill when:
- Starting a new Next.js project that needs Supabase authentication
- Adding email/password auth to an existing Supabase-enabled project
- Migrating from another auth provider to Supabase
- Troubleshooting Supabase auth errors (PKCE, cookies, sessions)
- Implementing admin panels with role-based access
- Setting up password reset flows
- User asks to "implement Supabase auth" or "add login functionality"
Prerequisites
Before using this skill, ensure:
- A Supabase project is created at https://supabase.com
- Next.js 13+ project with App Router (
app/directory) - Dependencies installed:
npm install @supabase/ssr @supabase/supabase-js npm install lucide-react # For icons in UI
Implementation Workflow
Step 1: Environment Variables Setup
Create or update the .env.local file with Supabase credentials.
Use the reference file: references/env-template.md for the exact environment variable structure.
Key variables needed:
NEXT_PUBLIC_SUPABASE_URL- Project URL from Supabase dashboardNEXT_PUBLIC_SUPABASE_ANON_KEY- Anon/public keySUPABASE_SERVICE_ROLE_KEY- Service role key (keep secret!)ADMIN_EMAILS- Comma-separated list of admin emails (optional)
Critical: Never commit .env.local to version control. Add it to .gitignore.
Step 2: Create Authentication Utilities
Create the core authentication utilities in the lib/auth/ directory.
Files to create:
-
lib/auth/client.ts- Client-side auth functions- Use template from
references/client-auth-template.md - Handles browser-based auth: sign in, sign up, password reset
- Creates Supabase browser client using
@supabase/ssr
- Use template from
-
lib/auth/server.ts- Server-side auth functions- Use template from
references/server-auth-template.md - Handles server component auth checks
- Implements admin role verification
- Proper Next.js 13+ cookie handling with
next/headers
- Use template from
-
lib/auth/api-protection.ts(Optional)- Use template from
references/api-protection-template.md - Helper functions for protecting API routes
- Validates authentication in API route handlers
- Use template from
-
lib/supabase-admin.ts- Admin client for bypassing RLS- Use template from
references/supabase-admin-template.md - Creates service role client for admin operations
- Required for checking user roles in database
- Use template from
Step 3: Create Auth Callback Handler
The auth callback route handles OAuth redirects and PKCE flow completion.
Create: app/auth/callback/route.ts
Use template from: references/auth-callback-template.md
This route:
- Exchanges authorization code for session
- Handles PKCE code verifier from cookies
- Redirects to appropriate page based on user role
- Manages password recovery flow
- Validates admin email whitelist
Critical implementation notes:
- Must use
@supabase/ssrcreateServerClientfor cookie access - Code verifier is automatically retrieved from cookies
- Error handling redirects to
/login?error=<error_type>
Step 4: Create Login Page
Create a full-featured login page with email/password auth.
Create: app/login/page.tsx
Use template from: references/login-page-template.md
Features:
- Email and password inputs with validation
- Error message display
- Loading states
- Auto-redirect if already logged in
- Admin vs regular user detection
- Handles redirect parameter for protected pages
- Optional Google OAuth integration (commented out by default)
UI/UX considerations:
- Show clear error messages
- Disable form during submission
- Validate email format client-side
- Minimum 6 character password requirement
Step 5: Create Registration Page
Create a user registration page with full validation.
Create: app/register/page.tsx
Use template from: references/register-page-template.md
Features:
- Full name, email, password, and confirm password fields
- Client-side validation
- Password strength requirements
- Success screen with auto-redirect
- Email format validation
- Already registered error handling
Note: Registration creates accounts, but admin access requires email whitelist approval.
Step 6: Create Password Reset Pages (Optional)
If password reset functionality is needed, create these pages:
-
app/forgot-password/page.tsx- Use template from
references/forgot-password-template.md - Sends password reset email
- Use template from
-
app/update-password/page.tsx- Use template from
references/update-password-template.md - Allows user to set new password after clicking email link
- Use template from
Step 7: Supabase Dashboard Configuration
Configure Supabase settings in the dashboard:
-
Email Auth Settings
- Navigate to Authentication > Providers > Email
- Enable Email provider
- Disable "Confirm email" if you don't want email verification
- Set Site URL to your production URL
- Add redirect URLs:
http://localhost:3000/auth/callback(development)https://yourdomain.com/auth/callback(production)
-
URL Configuration
- Go to Authentication > URL Configuration
- Set Redirect URLs (important for OAuth and password reset):
http://localhost:3000/auth/callback https://yourdomain.com/auth/callback
-
Email Templates (Optional)
- Customize email templates in Authentication > Email Templates
- Update password reset, confirmation emails
-
Database Setup (If using role-based auth)
- Create
app_userstable with columns:id(uuid, foreign key to auth.users)role(text: 'admin' | 'user')status(text: 'active' | 'inactive')created_at(timestamp)
- See
references/database-schema.mdfor full schema
- Create
Step 8: Protect Routes with Middleware (Optional)
To automatically redirect unauthenticated users, create middleware.
Create: middleware.ts (root level)
Use template from: references/middleware-template.md
Features:
- Automatic auth checking for protected routes
- Refresh session tokens
- Redirect to login with return URL
- Exclude public routes (login, register, etc.)
Step 9: Testing the Implementation
Follow this testing checklist:
Registration Flow:
- Navigate to
/register - Enter email, password, full name
- Submit form
- Verify success message
- Check Supabase dashboard > Authentication > Users for new user
Login Flow:
- Navigate to
/login - Enter registered email and password
- Submit form
- Verify redirect to
/directoryor/admin-panelbased on role - Check that session persists on page refresh
Password Reset Flow:
- Navigate to
/forgot-password - Enter registered email
- Check email inbox for reset link
- Click link (should redirect to
/update-password) - Enter new password
- Verify login works with new password
Admin Access:
- Add test email to
ADMIN_EMAILSin.env.local - Login with admin email
- Verify redirect to
/admin-panel - Test API route protection with
isAdmin()function
Common Errors and Solutions
PKCE Flow Errors
Error: "code_verifier not found" or "Invalid PKCE code"
Solution:
- Ensure using
@supabase/ssrpackage - Use
createBrowserClientfor client-side - Use
createServerClientwith proper cookie config for server-side - Verify callback route implements cookie handlers correctly
- Check that redirect URLs match exactly in Supabase dashboard
Cookie Issues
Error: "Cookies can only be modified in a Server Action or Route Handler"
Solution:
- Only call
createServerClientin Server Components, Route Handlers, or Server Actions - Use
createBrowserClientin Client Components - Add
'use client'directive to client components - Wrap cookie operations in try-catch blocks
Session Not Persisting
Error: User logged in but session lost on refresh
Solution:
- Verify callback route exchanges code properly
- Check browser cookies are enabled
- Ensure HTTPS in production (cookies may not work on HTTP)
- Verify
sameSitecookie settings
Admin Access Not Working
Error: Admin users can't access admin panel
Solution:
- Check
ADMIN_EMAILSformat (comma-separated, no spaces unless trimmed) - Verify email matches exactly (case-sensitive)
- If using database roles, ensure
app_userstable exists - Check
isAdmin()function is called server-side only
Email Not Sending
Error: Password reset or confirmation emails not arriving
Solution:
- Check Supabase email rate limits
- Verify SMTP settings if using custom SMTP
- Check spam folder
- Use Supabase dashboard to resend confirmation
- For production, configure custom SMTP in Supabase
Customization Options
OAuth Providers (Google, GitHub, etc.)
To add Google OAuth:
- Enable Google provider in Supabase dashboard
- Configure OAuth credentials (Client ID, Secret)
- Uncomment Google sign-in code in
references/login-page-template.md - Add
signInWithGoogle()function import fromlib/auth/client.ts
Custom Role Systems
To extend beyond admin/user roles:
- Create
app_userstable with role column - Modify
isAdmin()to check specific roles - Create role-specific middleware helpers
- Add role checks in protected routes
Email Customization
Customize email templates in Supabase dashboard:
- Magic link templates
- Password reset templates
- Confirmation emails
- Add your branding
UI Theming
The provided templates use a purple gradient theme. To customize:
- Update Tailwind classes in login/register pages
- Modify color schemes in templates
- Replace Lucide icons with your preferred icon library
- Adjust form layouts and spacing
Advanced Features
Session Management
Refresh tokens automatically:
@supabase/ssrhandles refresh automatically- No manual refresh needed in most cases
- Tokens refresh on authenticated requests
Manual session refresh:
const { data, error } = await supabase.auth.refreshSession();
Sign out from all devices:
const { error } = await supabase.auth.signOut({ scope: 'global' });
Multi-tenancy
For multi-tenant apps:
- Add
organization_idtoapp_userstable - Filter queries by organization
- Implement organization-based RLS policies
- Add organization context to session
Social Auth (Google, GitHub, etc.)
- Enable provider in Supabase dashboard
- Configure OAuth credentials
- Add provider button to login page
- Use
signInWithOAuth()in client.ts - Handle callback in
app/auth/callback/route.ts
File Structure Reference
After implementation, your project structure should include:
your-project/
├── .env.local (environment variables)
├── middleware.ts (optional - route protection)
├── app/
│ ├── login/
│ │ └── page.tsx
│ ├── register/
│ │ └── page.tsx
│ ├── forgot-password/
│ │ └── page.tsx (optional)
│ ├── update-password/
│ │ └── page.tsx (optional)
│ └── auth/
│ └── callback/
│ └── route.ts
└── lib/
├── auth/
│ ├── client.ts
│ ├── server.ts
│ └── api-protection.ts (optional)
└── supabase-admin.ts
Best Practices
-
Security:
- Never expose service role key to client
- Always validate on server-side
- Use RLS policies in Supabase
- Sanitize user inputs
- Use HTTPS in production
-
Error Handling:
- Show user-friendly error messages
- Log detailed errors server-side
- Handle all auth error cases
- Provide clear next steps for users
-
Performance:
- Cache admin status checks
- Use Server Components for auth checks
- Minimize client-side auth calls
- Lazy load auth-related components
-
User Experience:
- Show loading states
- Provide clear feedback
- Auto-redirect after actions
- Remember redirect intentions
- Clear error messages
-
Testing:
- Test all auth flows
- Test error cases
- Test admin vs regular user paths
- Test password reset
- Test session persistence
Quick Reference
Sign up user:
import { signUpWithPassword } from '@/lib/auth/client';
const { data, error } = await signUpWithPassword(email, password, fullName);
Sign in user:
import { signInWithPassword } from '@/lib/auth/client';
const { data, error } = await signInWithPassword(email, password);
Get current user (client):
import { getUser } from '@/lib/auth/client';
const { user, error } = await getUser();
Get current user (server):
import { getUser } from '@/lib/auth/server';
const { user, error } = await getUser();
Check if admin (server):
import { isAdmin } from '@/lib/auth/server';
const admin = await isAdmin();
Sign out:
import { signOut } from '@/lib/auth/client';
const { error } = await signOut();
Reset password:
import { resetPassword } from '@/lib/auth/client';
const { data, error } = await resetPassword(email);
Update password:
import { updatePassword } from '@/lib/auth/client';
const { data, error } = await updatePassword(newPassword);
Support and Resources
- Supabase Auth Docs: https://supabase.com/docs/guides/auth
- @supabase/ssr Docs: https://supabase.com/docs/guides/auth/server-side/nextjs
- Next.js App Router: https://nextjs.org/docs/app
- Common Issues: Check
references/troubleshooting.md