Skip to main content

Authentication API

The Authentication API provides client-side functions for handling user authentication, authorization, and session management using Clerk.

Core Features

  • User Authentication: Sign-up, sign-in, and sign-out functionality
  • Session Management: Managing and validating user sessions
  • Role-Based Access Control: Authorization based on user roles
  • Error Handling: Standardized authentication error handling
  • Infrastructure Foundation: Complete type safety and handler signature standardization (v2.0.0)

Session 8 Infrastructure Completion (v2.0.0)

Middleware Infrastructure Standardization

All authentication middleware now uses the standardized AuthObject pattern for complete type safety and consistency.

Standard AuthObject Interface

interface AuthObject {
  userId: string;
  roles: UserRole[];
  claims: ClerkSessionClaims | null;
  permissions?: Permission[];
}

API Route Handler Standardization

All API routes now use the unified pattern:
import { withAuth, withOptionalAuth } from '@/lib/auth';

// Protected routes
export const POST = withAuth(async (request, context, auth) => {
  const { userId, roles } = auth;
  // Type-safe implementation
});

// Optional authentication
export const GET = withOptionalAuth(async (request, context, auth?) => {
  const userId = auth?.userId;
  // Optional auth handling
});

Infrastructure Foundation Complete ✅

  • Profile Authentication Middleware: Enhanced with proper Prisma relations and type safety
  • Middleware Configuration: Complete environment configurations across development/production/test
  • API Handler Signatures: Standardized across entire platform (24 errors eliminated)
  • Type Safety: 100% TypeScript coverage in authentication infrastructure

API Reference

Authentication

signIn
function
Authenticate a user with email and password
async function signIn(
  email: string,
  password: string
): Promise<SignInResult>
signOut
function
Sign the current user out
async function signOut(): Promise<void>
signUp
function
Register a new user with email and password
async function signUp(
  email: string,
  password: string,
  firstName: string,
  lastName: string
): Promise<SignUpResult>

Session Management

getServerAuth
function
Get authentication state from server context
function getServerAuth(): ServerAuth
getOptionalServerAuth
function
Get authentication state without requiring authentication
function getOptionalServerAuth(): ServerAuth | AuthNotAuthenticated
requireAuth
function
Higher-order function that requires authentication
function requireAuth<T>(
  handler: (req: NextRequest, auth: ServerAuth) => Promise<T>,
  options?: AuthOptions
): (req: NextRequest) => Promise<T | Response>

Role-Based Access Control

requireRole
function
Higher-order function that requires a specific role
function requireRole<T>(
  role: UserRole,
  handler: (req: NextRequest, auth: ServerAuth) => Promise<T>,
  options?: AuthOptions
): (req: NextRequest) => Promise<T | Response>
requirePermission
function
Higher-order function that requires a specific permission
function requirePermission<T>(
  permission: Permission,
  handler: (req: NextRequest, auth: ServerAuth) => Promise<T>,
  options?: AuthOptions
): (req: NextRequest) => Promise<T | Response>

Usage Examples

Protecting API Routes (Updated v2.0.0)

// app/api/protected/route.ts
import { withAuth } from '@/lib/auth';
import { NextRequest, NextResponse } from 'next/server';
import { toStandardResponse } from '@/lib/types/api-types';

export const GET = withAuth(async (
  req: NextRequest, 
  context: { params?: any }, 
  auth: AuthObject
) => {
  // This code only runs for authenticated users
  // auth object contains: { userId, roles, claims, permissions? }
  return NextResponse.json(toStandardResponse({
    message: `Hello, authenticated user ${auth.userId}!`,
    userRoles: auth.roles
  }));
});

Role-Based Access Control (Updated v2.0.0)

// app/api/admin/route.ts
import { withRole } from '@/lib/auth';
import { UserRole } from '@/lib/auth/types';
import { NextRequest, NextResponse } from 'next/server';
import { toStandardResponse } from '@/lib/types/api-types';

export const GET = withRole(UserRole.ADMIN, async (
  req: NextRequest, 
  context: { params?: any }, 
  auth: AuthObject
) => {
  // This code only runs for admin users
  // auth.roles guaranteed to include UserRole.ADMIN
  return NextResponse.json(toStandardResponse({
    message: 'Hello, admin!',
    adminPrivileges: true,
    userId: auth.userId
  }));
});

Server Component Authentication

// app/profile/page.tsx
import { getServerAuth } from '@/lib/auth';
import { redirect } from 'next/navigation';

export default async function ProfilePage() {
  const auth = getServerAuth();
  
  if (!auth.isAuthenticated) {
    redirect('/login');
  }
  
  return (
    <div>
      <h1>Welcome, {auth.user.firstName}!</h1>
      {/* Profile content */}
    </div>
  );
}

Hybrid Authentication (For Both Auth and Non-Auth Users)

// app/sessions/[id]/page.tsx
import { getOptionalServerAuth } from '@/lib/auth';
import { getSessionById } from '@/lib/sessions/api';

export default async function SessionDetailPage({ params }) {
  const { id } = params;
  const auth = getOptionalServerAuth();
  const session = await getSessionById(id);
  
  // Public sessions are visible to everyone
  if (session.isPublic) {
    return <PublicSessionView session={session} isAuthenticated={auth.isAuthenticated} />;
  }
  
  // Private sessions require authentication
  if (!auth.isAuthenticated) {
    return <SessionRequiresAuthView sessionId={id} />;
  }
  
  // User-specific session view for authenticated users
  return <AuthenticatedSessionView session={session} userId={auth.userId} />;
}

Error Handling

The auth API provides standardized error handling through typed error responses:
// Example error handling
try {
  const result = await signIn(email, password);
  if (!result.success) {
    // Handle specific error cases
    switch (result.error) {
      case 'invalid_credentials':
        showErrorMessage('Invalid email or password');
        break;
      case 'account_locked':
        showErrorMessage('Your account has been temporarily locked');
        break;
      default:
        showErrorMessage('An error occurred during sign in');
    }
  }
} catch (error) {
  // Handle unexpected errors
  console.error('Authentication error:', error);
  showErrorMessage('Authentication service unavailable');
}

See Also