Skip to main content

Authentication Overview

TalentG uses Supabase Auth for user authentication, providing secure login, registration, and session management.

Authentication Flow

User Registration

Email/Password Registration

import { createClient } from '@supabase/supabase-js'

const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)

// Register new user
const { data, error } = await supabase.auth.signUp({
  email: 'user@example.com',
  password: 'securepassword',
  options: {
    data: {
      first_name: 'John',
      last_name: 'Doe',
      role: 'user'
    }
  }
})

OAuth Providers

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

// GitHub OAuth
const { data, error } = await supabase.auth.signInWithOAuth({
  provider: 'github',
  options: {
    redirectTo: `${window.location.origin}/auth/callback`
  }
})

User Login

Email/Password Login

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

Session Management

Get Current User

// Get current session
const { data: { session } } = await supabase.auth.getSession()

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

Listen to Auth Changes

useEffect(() => {
  const { data: { subscription } } = supabase.auth.onAuthStateChange(
    (event, session) => {
      if (event === 'SIGNED_IN') {
        // User signed in
        router.push('/dashboard')
      } else if (event === 'SIGNED_OUT') {
        // User signed out
        router.push('/login')
      }
    }
  )

  return () => subscription.unsubscribe()
}, [])

User Profiles

Profile Creation

// Create user profile after registration
const createProfile = async (user: User) => {
  const { data, error } = await supabase
    .from('profiles')
    .insert({
      id: user.id,
      first_name: user.user_metadata.first_name,
      last_name: user.user_metadata.last_name,
      role: user.user_metadata.role || 'user'
    })
}

Profile Updates

const updateProfile = async (updates: Partial<Profile>) => {
  const { data, error } = await supabase
    .from('profiles')
    .update(updates)
    .eq('id', user.id)
}

Role-Based Access Control

User Roles

enum UserRole {
  ADMIN = 'admin',
  MANAGER = 'manager',
  TELECALLER = 'telecaller',
  USER = 'user'
}

Role Checking

// Check user role
const hasRole = (userRole: string, requiredRole: string) => {
  const roleHierarchy = {
    'user': 1,
    'telecaller': 2,
    'manager': 3,
    'admin': 4
  }
  
  return roleHierarchy[userRole] >= roleHierarchy[requiredRole]
}

// Usage
if (hasRole(user.role, 'manager')) {
  // Show manager features
}

Protected Routes

// Middleware for protected routes
export function withAuth(requiredRole?: string) {
  return function (WrappedComponent: React.ComponentType) {
    return function AuthenticatedComponent(props: any) {
      const { user, loading } = useAuth()
      
      if (loading) return <LoadingSpinner />
      
      if (!user) {
        router.push('/login')
        return null
      }
      
      if (requiredRole && !hasRole(user.role, requiredRole)) {
        router.push('/unauthorized')
        return null
      }
      
      return <WrappedComponent {...props} />
    }
  }
}

Database Security

Row Level Security (RLS)

-- Enable RLS on profiles table
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;

-- Users can only see their own profile
CREATE POLICY "Users can view own profile" ON profiles
  FOR SELECT USING (auth.uid() = id);

-- Users can update their own profile
CREATE POLICY "Users can update own profile" ON profiles
  FOR UPDATE USING (auth.uid() = id);

-- Admins can see all profiles
CREATE POLICY "Admins can view all profiles" ON profiles
  FOR SELECT USING (
    EXISTS (
      SELECT 1 FROM profiles 
      WHERE id = auth.uid() AND role = 'admin'
    )
  );

API Route Protection

// pages/api/protected-route.ts
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'

export async function GET(request: Request) {
  const supabase = createRouteHandlerClient({ cookies })
  
  const { data: { session } } = await supabase.auth.getSession()
  
  if (!session) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 })
  }
  
  // Check user role
  const { data: profile } = await supabase
    .from('profiles')
    .select('role')
    .eq('id', session.user.id)
    .single()
  
  if (profile.role !== 'admin') {
    return Response.json({ error: 'Forbidden' }, { status: 403 })
  }
  
  // Protected logic here
  return Response.json({ data: 'Protected data' })
}

Password Management

Password Reset

const resetPassword = async (email: string) => {
  const { data, error } = await supabase.auth.resetPasswordForEmail(email, {
    redirectTo: `${window.location.origin}/auth/reset-password`
  })
}

Password Update

const updatePassword = async (newPassword: string) => {
  const { data, error } = await supabase.auth.updateUser({
    password: newPassword
  })
}

Security Best Practices

Password Requirements

  • Minimum 8 characters
  • Mix of uppercase, lowercase, numbers, and symbols
  • No common passwords
  • Regular password updates

Session Security

  • JWT tokens with expiration
  • Secure cookie settings
  • HTTPS only in production
  • Regular session validation

Data Protection

  • Encrypted data transmission
  • Secure database connections
  • Regular security audits
  • User data anonymization options