ShipKit

Authentication

Set up user authentication with Supabase Auth

Authentication

This boilerplate uses Supabase Auth for authentication, providing email/password login, magic links, and OAuth support.

Configuration

1. Create a Supabase Project

  1. Go to supabase.com and create a new project
  2. Note your project URL and anon key from Settings → API

2. Set Environment Variables

Add to your .env.local:

NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key

3. Configure Redirect URLs

In Supabase Dashboard → Authentication → URL Configuration:

  • Site URL: http://localhost:3000 (dev) or your production URL
  • Redirect URLs:
    • http://localhost:3000/auth/callback
    • https://yourdomain.com/auth/callback

How It Works

Client-Side Auth

import { createClient } from "@/lib/supabase/client";

const supabase = createClient();

// Sign up
const { data, error } = await supabase.auth.signUp({
  email: "user@example.com",
  password: "password123",
});

// Sign in
const { data, error } = await supabase.auth.signInWithPassword({
  email: "user@example.com",
  password: "password123",
});

// Sign out
await supabase.auth.signOut();

Server-Side Auth

import { createClient } from "@/lib/supabase/server";

export async function getUser() {
  const supabase = await createClient();
  const { data: { user } } = await supabase.auth.getUser();
  return user;
}

Protected Routes

Routes under /dashboard are automatically protected via middleware. The middleware checks for a valid session and redirects to /auth/login if not authenticated.

// src/lib/supabase/middleware.ts
export async function updateSession(request: NextRequest) {
  // Session is validated and refreshed automatically
}

Enable passwordless login with magic links:

const { error } = await supabase.auth.signInWithOtp({
  email: "user@example.com",
  options: {
    emailRedirectTo: `${window.location.origin}/auth/callback`,
  },
});

OAuth (Google, GitHub)

Enable OAuth in Supabase

  1. Go to Authentication → Providers
  2. Enable Google/GitHub
  3. Add your OAuth credentials

Use in Your App

const { error } = await supabase.auth.signInWithOAuth({
  provider: "google",
  options: {
    redirectTo: `${window.location.origin}/auth/callback`,
  },
});

Password Reset

The password reset flow is already implemented:

  1. User visits /auth/forgot-password
  2. Enters email and receives a reset link
  3. Link redirects to /auth/reset-password
  4. User enters new password

User Profiles

User profiles are stored in the profiles table with Row Level Security (RLS):

create table profiles (
  id uuid references auth.users on delete cascade primary key,
  full_name text,
  avatar_url text,
  updated_at timestamptz default now()
);

-- Enable RLS
alter table profiles enable row level security;

-- Users can only read/update their own profile
create policy "Users can view own profile"
  on profiles for select using (auth.uid() = id);

create policy "Users can update own profile"
  on profiles for update using (auth.uid() = id);

Hooks

Use the useUser hook to access user data in client components:

import { useUser } from "@/hooks/use-user";

export function ProfileButton() {
  const { user, profile, loading } = useUser();

  if (loading) return <Skeleton />;
  if (!user) return <LoginButton />;

  return <Avatar src={profile?.avatar_url} />;
}

On this page