Skip to main content

Email + Password Authentication

Email/password is the traditional authentication method. Users create an account with their email and a password they choose.
Consider your use case. For subscription apps with paywalls, anonymous auth often converts better. Email auth adds friction before users see your app’s value.

Overview

Email authentication is the simplest to set up:
  1. Supabase Dashboard — Enable Email provider (usually already enabled)
  2. Your App — Use the pre-built forms and auth functions
Time required: ~10 minutes

Part 1: Supabase Configuration

Enable Email Provider

1

Open Auth settings

Go to your Supabase project dashboardNavigate to Authentication → Providers
2

Check Email is enabled

Find Email in the listIt should be enabled by default. If not, toggle it on.

Configure Email Settings (Optional)

1

Open Email Templates

Go to Authentication → Email Templates
2

Customize templates

You can customize:
  • Confirm signup — Email sent when user signs up
  • Reset password — Email sent when user requests password reset
  • Magic link — Email for passwordless login (if enabled)
Each template supports variables like {{ .ConfirmationURL }}

Security Settings (Optional)

Go to Authentication → Settings to configure:
SettingRecommendation
Confirm emailEnable for production (prevents fake signups)
Secure email changeEnable (requires confirmation for email changes)
Min password length8+ characters recommended

Part 2: App Configuration

Step 1: Enable in App Config

Update config/app.config.ts:
auth: {
  mode: 'required', // Users must sign in
  providers: {
    email: true,  // Enable email/password
    apple: false,
    google: false,
  },
}

Step 2: Use Auth Functions

The kit provides these email auth functions in lib/auth.ts:
import { signInWithEmail, signUpWithEmail, resetPassword } from '@/lib/auth';

// Sign in existing user
await signInWithEmail('user@example.com', 'password123');

// Create new account
await signUpWithEmail('user@example.com', 'password123');

// Send password reset email
await resetPassword('user@example.com');

Step 3: Use Pre-built Screens

Navigate to the auth screens:
import { useRouter } from 'expo-router';

const router = useRouter();

// Go to login
router.push('/auth/login');

// Go to signup
router.push('/auth/signup');

// Go to forgot password
router.push('/auth/forgot-password');

Using the Components

Login Form

import { LoginForm } from '@/components/auth';

<LoginForm
  onSuccess={() => {
    // User signed in successfully
    router.replace('/(main)');
  }}
  onForgotPassword={() => {
    router.push('/auth/forgot-password');
  }}
  onSignUp={() => {
    router.push('/auth/signup');
  }}
/>

Signup Form

import { SignupForm } from '@/components/auth';

<SignupForm
  onSuccess={() => {
    // Account created - user needs to verify email
    Alert.alert(
      'Check your email',
      'We sent you a confirmation link.'
    );
  }}
  onLogin={() => {
    router.push('/auth/login');
  }}
/>

Forgot Password Form

import { ForgotPasswordForm } from '@/components/auth';

<ForgotPasswordForm
  onSuccess={() => {
    // Email sent
    Alert.alert('Email sent', 'Check your inbox for reset instructions.');
  }}
  onBack={() => {
    router.back();
  }}
/>

Email Verification Flow

When email confirmation is enabled (recommended for production):
  1. User signs up with email/password
  2. Supabase sends confirmation email
  3. User clicks link in email
  4. User is verified and can sign in

Handling Unverified Users

import { useAuth } from '@/contexts/auth-context';

const { user } = useAuth();

// Check if email is confirmed
if (user && !user.email_confirmed_at) {
  // Show "Please verify your email" message
}

Customizing the Input Component

The kit includes a reusable AuthInput component:
import { AuthInput } from '@/components/auth';

<AuthInput
  label="Email"
  placeholder="you@example.com"
  icon="mail-outline"
  value={email}
  onChangeText={setEmail}
  keyboardType="email-address"
  autoComplete="email"
/>

<AuthInput
  label="Password"
  placeholder="Enter password"
  icon="lock-closed-outline"
  value={password}
  onChangeText={setPassword}
  secureTextEntry // Shows eye toggle for password visibility
  autoComplete="password"
  error={passwordError} // Shows error message below input
/>

Combining with Social Auth

You can offer both email and social authentication:
import { AuthDivider, LoginForm, SocialAuthButtons } from '@/components/auth';

// In your login screen
<SocialAuthButtons
  showApple={true}
  showGoogle={true}
  onSuccess={handleSuccess}
/>

<AuthDivider text="or sign in with email" />

<LoginForm
  onSuccess={handleSuccess}
  onForgotPassword={() => router.push('/auth/forgot-password')}
/>

Error Handling

Common errors and how to handle them:
ErrorMeaningUser Message
Invalid login credentialsWrong email or password”Invalid email or password”
User already registeredEmail already exists”An account with this email already exists”
Password should be at least X charactersPassword too short”Password must be at least X characters”
Email not confirmedUser hasn’t verified email”Please verify your email first”
The LoginForm and SignupForm components handle these automatically.

Testing

In Development

  1. Sign up with a real email you can access
  2. Check your inbox for the confirmation email
  3. Click the link to verify
  4. Sign in with your credentials

Test Accounts

For testing without real emails, you can:
  1. Disable email confirmation in Supabase (development only)
  2. Use Supabase’s Inbucket for local email testing

Next Steps