챕터
3. 인증

Authentication: Building Login Features

Learning Objectives

  • Understand what Authentication is
  • Implement login functionality with Supabase Auth
  • Integrate social login (Google, GitHub)
  • Control page access based on login status

3.1 What is Authentication?

Authentication vs Authorization

ConceptMeaningExample
AuthenticationVerify "who you are"Login
AuthorizationVerify "what you can do"Only admins can delete

Why Not Build It Yourself?

Building authentication yourself requires considering too many things:

  • Password encryption (hashing, salting)
  • Session/token management
  • Security vulnerability prevention (CSRF, XSS)
  • Password recovery, email verification...

That's why we use services like Supabase Auth. It's free and already security-verified.


3.2 Magic Link Login

Magic Link is a passwordless login via email. Click the link and you're logged in.

Creating Login Page

Create a login page.
- Email input field
- "Send Login Link" button
- Use Supabase Auth's Magic Link
- Show loading state and success message

How It Works

  1. User enters email
  2. Supabase sends login link to email
  3. User clicks link
  4. Automatically logged in → Navigate to dashboard
// Magic Link login request
const { error } = await supabase.auth.signInWithOtp({
  email: email,
  options: {
    emailRedirectTo: window.location.origin + '/dashboard'
  }
})

3.3 Social Login Integration

Adding social logins like Google and GitHub makes it easier for users to sign up.

Google Login Setup

Google Cloud Console Setup

  1. Go to Google Cloud Console (console.cloud.google.com)
  2. Create new project
  3. APIs & Services → Credentials → Create Credentials → OAuth client ID
  4. Select Web application
  5. Add to Authorized redirect URIs: https://[projectID].supabase.co/auth/v1/callback
  6. Copy Client ID and Secret

Supabase Integration

  1. Supabase Dashboard → Auth → Providers → Google → Enable and enter keys

GitHub Login Setup

  1. GitHub Settings → Developer settings → OAuth Apps → New OAuth App
  2. Authorization callback URL: https://[projectID].supabase.co/auth/v1/callback
  3. Copy Client ID and Secret
  4. Enable GitHub Provider in Supabase

Adding Social Login Buttons

Add Google and GitHub social login buttons to the login page.
Use Supabase Auth's signInWithOAuth.
Style buttons with each brand's colors.
// Google login
await supabase.auth.signInWithOAuth({
  provider: 'google',
  options: { redirectTo: window.location.origin + '/dashboard' }
})
 
// GitHub login
await supabase.auth.signInWithOAuth({
  provider: 'github',
  options: { redirectTo: window.location.origin + '/dashboard' }
})

3.4 Managing Login State

Checking Current User

// Get currently logged in user
const { data: { user } } = await supabase.auth.getUser()
 
if (user) {
  console.log('Logged in:', user.email)
} else {
  console.log('Not logged in')
}

Modifying Header Component

Modify the header.
- If not logged in: "Login" button
- If logged in: user email, profile icon, "Logout" button

Check Supabase session to handle this.

Implementing Logout

const handleLogout = async () => {
  await supabase.auth.signOut()
  router.push('/') // Navigate to home
}

3.5 Page Access Control

Dashboard should only be accessible to logged-in users.

Protecting with Middleware

Create Next.js middleware:
- All pages starting with /dashboard require login
- If not logged in, redirect to /login
- If already logged in and going to /login, redirect to /dashboard

Check Supabase session to handle this.

3.6 Row Level Security (RLS)

RLS is a feature that enforces "access only your own data" at the database level.

Why Is It Needed?

Even if you check user_id on the frontend, malicious users can access other people's data by calling the API directly. RLS blocks this at the database.

Setting Up RLS Policies

Run in Supabase SQL Editor:

-- Enable RLS on profiles table
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
 
-- Profiles are publicly viewable (for public profile pages)
CREATE POLICY "Profiles are publicly viewable"
ON profiles FOR SELECT
USING (true);
 
-- Can only create own profile
CREATE POLICY "Users can create own profile"
ON profiles FOR INSERT
WITH CHECK (auth.uid() = user_id);
 
-- Can only update own profile
CREATE POLICY "Users can update own profile"
ON profiles FOR UPDATE
USING (auth.uid() = user_id);
 
-- Enable RLS on links table
ALTER TABLE links ENABLE ROW LEVEL SECURITY;
 
-- Links are publicly viewable (for public profile pages)
CREATE POLICY "Links are publicly viewable"
ON links FOR SELECT
USING (true);
 
-- Can only create links for own profile
CREATE POLICY "Users can create own links"
ON links FOR INSERT
WITH CHECK (profile_id IN (
  SELECT id FROM profiles WHERE user_id = auth.uid()
));
 
-- Can only update/delete own links
CREATE POLICY "Users can update own links"
ON links FOR UPDATE
USING (profile_id IN (
  SELECT id FROM profiles WHERE user_id = auth.uid()
));
 
CREATE POLICY "Users can delete own links"
ON links FOR DELETE
USING (profile_id IN (
  SELECT id FROM profiles WHERE user_id = auth.uid()
));

What is auth.uid()?

auth.uid() is a Supabase function that returns the currently logged-in user's ID. Returns null if not logged in.


3.7 Other Authentication Options

Besides Supabase Auth, there are other authentication services suitable for vibe coding.

Options Comparison

ServiceFeaturesFree TierRecommended For
Supabase AuthDB integrated, RLS supportUnlimited MAUWhen using Supabase DB
ClerkEasiest, provides components10,000 MAUQuick implementation
Auth.jsOpen source, flexibleFree (self-hosted)Need customization
Firebase AuthGoogle ecosystemUnlimitedWhen using Firebase DB
LuciaLightweight, type-safeFree (self-hosted)Want direct control
KindeFast setup, B2B features7,500 MAUNeed enterprise features

Clerk

The easiest authentication solution. Even provides UI components.

Implement authentication with Clerk.
Use @clerk/nextjs package.
Include social login (Google, GitHub).
// Clerk usage example
import { SignIn, SignUp, UserButton } from '@clerk/nextjs';
 
// Login page
export default function LoginPage() {
  return <SignIn />;
}
 
// User button in header
<UserButton afterSignOutUrl="/" />

Clerk's Advantages

  • Auto-generate UI with <SignIn />, <SignUp /> components
  • Protect pages with one line of middleware
  • Provides user management dashboard

Auth.js (NextAuth.js)

Open source and most flexible. Supports various Providers.

Implement authentication with Auth.js (NextAuth).
Use next-auth package.
Include Google, GitHub, email login.
Store sessions in DB with Prisma adapter.
// Auth.js setup example
import NextAuth from 'next-auth';
import Google from 'next-auth/providers/google';
import GitHub from 'next-auth/providers/github';
 
export const { handlers, auth, signIn, signOut } = NextAuth({
  providers: [Google, GitHub],
});

Firebase Auth

Natural choice if you're using Google ecosystem.

Implement authentication with Firebase Auth.
Use firebase package.
Include Google, GitHub social login.

Lucia

Lightweight and type-safe authentication library. Good when you need direct control.

Implement authentication with Lucia.
Use lucia package.
Store sessions in Supabase.

Which One Should You Choose?

SituationRecommendation
Using Supabase DBSupabase Auth
Want quickest implementationClerk
Need full customizationAuth.js
Using Firebase DBFirebase Auth
Want lightweight, direct controlLucia
B2B SaaS, need organization managementKinde
💡

Vibe Coding Tip

Authentication is hard to change later. Choose carefully from the start. If unsure, recommend Supabase Auth (DB integrated) or Clerk (easiest).


Chapter Summary

  • Understood the difference between authentication and authorization
  • Implemented Magic Link email login
  • Integrated Google, GitHub social login
  • Changed UI based on login status
  • Protected pages with middleware
  • Controlled data access with RLS
  • Learned about various authentication options

In the next chapter, we'll implement real-time communication.

Chapter 4: Real-time Features →