Bỏ qua

Authentication Concepts

Supabase Auth Overview

Supabase Auth (GoTrue) là authentication service tích hợp sẵn.

┌─────────────────────────────────────────────────────────────┐
│                    SUPABASE AUTH                             │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌─────────────────────────────────────────────────────┐    │
│  │                  Auth Methods                        │    │
│  │  ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐   │    │
│  │  │  Email  │ │  OAuth  │ │  Phone  │ │  Magic  │   │    │
│  │  │Password │ │(Google) │ │   OTP   │ │  Link   │   │    │
│  │  └─────────┘ └─────────┘ └─────────┘ └─────────┘   │    │
│  └─────────────────────────────────────────────────────┘    │
│                           │                                  │
│                           ▼                                  │
│  ┌─────────────────────────────────────────────────────┐    │
│  │                   JWT Token                          │    │
│  │           (Access Token + Refresh Token)             │    │
│  └─────────────────────────────────────────────────────┘    │
│                           │                                  │
│                           ▼                                  │
│  ┌─────────────────────────────────────────────────────┐    │
│  │              Row Level Security                      │    │
│  │           auth.uid() = user_id                       │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                              │
└─────────────────────────────────────────────────────────────┘

Auth Methods

Available Methods

Method Description Use Case
Email/Password Traditional signup Most common
Magic Link Passwordless email Low friction
Phone OTP SMS verification Mobile apps
OAuth Google, GitHub, etc. Social login
SAML SSO Enterprise SSO B2B apps
Anonymous Temporary accounts Try before signup

Enable in Dashboard

Authentication → Providers → Enable desired providers

JWT Tokens

Token Structure

// Access Token (JWT)
{
  "aud": "authenticated",
  "exp": 1705312800,  // Expiration (1 hour default)
  "sub": "user-uuid-here",  // User ID
  "email": "user@example.com",
  "role": "authenticated",
  "app_metadata": {
    "provider": "email"
  },
  "user_metadata": {
    "full_name": "John Doe"
  }
}

Token Flow

┌─────────┐     ┌─────────┐     ┌─────────┐
│  Login  │────▶│  Auth   │────▶│  JWT    │
│         │     │ Server  │     │ Tokens  │
└─────────┘     └─────────┘     └─────────┘
                    ┌────────────────┴────────────────┐
                    ▼                                 ▼
              ┌──────────┐                    ┌──────────┐
              │  Access  │                    │ Refresh  │
              │  Token   │                    │  Token   │
              │ (1 hour) │                    │ (7 days) │
              └──────────┘                    └──────────┘
                    │                                │
                    ▼                                ▼
              API Requests                   Renew Access Token

Session Management

Session Storage

// Browser: Stored in localStorage or cookies
// supabase-js handles this automatically

const { data: { session } } = await supabase.auth.getSession();
// session.access_token
// session.refresh_token
// session.user

Session Events

// Listen for auth state changes
supabase.auth.onAuthStateChange((event, session) => {
  console.log('Auth event:', event);
  // Events: SIGNED_IN, SIGNED_OUT, TOKEN_REFRESHED, USER_UPDATED

  if (event === 'SIGNED_IN') {
    // User logged in
  }

  if (event === 'SIGNED_OUT') {
    // User logged out
  }

  if (event === 'TOKEN_REFRESHED') {
    // Token was refreshed
  }
});

User Object

User Structure

interface User {
  id: string;                    // UUID
  email?: string;
  phone?: string;
  created_at: string;
  updated_at: string;
  last_sign_in_at: string;
  email_confirmed_at?: string;
  phone_confirmed_at?: string;

  app_metadata: {
    provider: string;           // 'email', 'google', etc.
    providers: string[];
  };

  user_metadata: {
    full_name?: string;
    avatar_url?: string;
    // Custom fields
  };
}

Access User Data

// Get current user
const { data: { user } } = await supabase.auth.getUser();

if (user) {
  console.log('User ID:', user.id);
  console.log('Email:', user.email);
  console.log('Name:', user.user_metadata.full_name);
}

Auth + RLS Integration

How it Works

-- RLS policy using auth.uid()
CREATE POLICY "Users can only see own data"
  ON public.tasks
  FOR SELECT
  USING (auth.uid() = user_id);

-- auth.uid() extracts user ID from JWT automatically

Auth Helper Functions

-- Get current user ID
SELECT auth.uid();

-- Get current user role
SELECT auth.role();

-- Get current user email
SELECT auth.email();

-- Get JWT claim
SELECT auth.jwt() ->> 'email';

Security Best Practices

Client vs Server

// ✅ Client-side: Use anon key
const supabase = createClient(url, anonKey);
// RLS protects data automatically

// ✅ Server-side: Can use service role for admin tasks
const supabaseAdmin = createClient(url, serviceRoleKey);
// Bypasses RLS - use carefully!

Secure Patterns

// ✅ Always verify session server-side
export async function GET(request: Request) {
  const supabase = await createServerClient();
  const { data: { user }, error } = await supabase.auth.getUser();

  if (!user) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 });
  }

  // Proceed with authenticated request
}

// ❌ Don't trust client-provided user ID
// Always use auth.uid() in queries

Email Configuration

Email Templates

Authentication → Email Templates

Templates:
- Confirm signup
- Invite user
- Magic Link
- Change Email
- Reset Password

Custom SMTP

Project Settings → Authentication → SMTP Settings

Configure:
- Host, Port
- Username, Password
- Sender email

Tổng kết

Key Concepts

  1. JWT-based - Stateless authentication
  2. Multiple providers - Email, OAuth, Phone
  3. RLS integration - auth.uid() in policies
  4. Auto refresh - Tokens refresh automatically
  5. Session events - React to auth changes

Auth Flow Summary

Signup/Login → JWT issued → Store in browser
API Request → Include JWT → Validate → auth.uid()
RLS Policy → Filter data → Return results

Q&A

  1. Đã implement auth trước đây chưa?
  2. Cần OAuth providers nào?
  3. Có requirements về session length?