OAuth Master Class

Jun 28, 2024

Oauth Master Class Notes

Introduction

  • Topic: NextAuth.js v5
  • Covered Topics:
    • Credential and social providers integration
    • Forgot Password & Email Verification
    • Two Factor Authentication
    • Managing User Roles (Admin, User)
    • Building a Reusable Toolkit (Components, Hooks, Utilities)
  • Usage Contexts: Server Components, Client Components, Models, Pages, API Routes, Server Actions

Setting Up the Project

System Requirements

  • Node.js v18.17 or later
  • IDE: Visual Studio Code

Steps:

  1. Confirm Node.js version:
    node -v
    
  2. Install Next.js:
    npx create-next-app@latest
    
  3. Setup Project Name & Configuration
    • Use TypeScript
    • Use ESLint
    • Use Tailwind CSS (for styling)
    • Do not use the source directory
    • Use the app router (select yes)
    • Do not customize the default import aliases

Project Configuration

  • Install & Setup Shad CN UI
    npx shadcn-ui@latest init
    
    • Select: Typescript, New York style, Slate color
  1. Initialize Tailwind CSS
    npx shadcn-ui@latest add button
    
  2. Test Tailwind CSS Integration
    • Add a component, e.g., button with npx shadcn-ui add button
    • Check if Tailwind styles and Intellisense work correctly

Basic Page Setup

Landing Page

  1. Create a main landing page:

    <main className="flex min-h-screen items-center justify-center">
      <div className="space-y-6">
        <h1 className="text-6xl font-semibold text-center text-white drop-shadow-md">
          Oauth <span>🔒</span>
        </h1>
        <p className="text-lg text-center text-white">A Simple Authentication Service</p>
      </div>
    </main>
    
  2. Add a login button using the Button component.

Login Button Component

  • Create a LoginButton component
    • Modes: model, redirect
    • Handles redirection or model display based on the mode
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { Dialog } from '@headlessui/react';
//... Other Imports

const LoginButton = ({ mode, asChild, children }) => {
  const router = useRouter();

  // Logic for redirect or model dialog based on mode
};
  1. Integrate Component in Page

Routing in Next.js

Folder-based Routing

  1. Understand route segmentation
    • app/dashboard/page.tsx routes to /dashboard
    • Nested routes use nested folders

Special Files

  • layout.tsx - Shared UI elements (e.g., NavBar, Sidebar)
  • page.tsx - Unique UI for route

Applying Routing Principles

  1. Create folders for login & register under app/out
  2. Create corresponding pages and import relevant forms from components
    • Registration & Login Forms

Creating Forms and Schema Validation

Using Zod for Validation

  1. Install dependencies
    npm install @hookform/resolvers zod
    

Creating the Schemas

  1. *schemas/index.ts:
    import { z } from 'zod';
    export const loginSchema = z.object({
      email: z.string().email(),
      password: z.string()
    });
    //... More schemas
    

Building Forms

  1. Implement React Hook Form + Zod Resolver in your component

    import { zodResolver } from '@hookform/resolvers/zod';
    import { useForm } from 'react-hook-form';
    const { register, handleSubmit, formState: { errors } } = useForm({
      resolver: zodResolver(loginSchema),
    });
    
  2. Create input fields and display validation messages.

Server Actions

Setting Up Server Actions

  1. Use server mark for server-side actions

    export const registerUser = async (values) => {
      'use server';
      // ...implementation
    };
    
  2. Implementations

    • registerUser: Encrypt password, create user in DB, send verification email
    • loginUser: Validate user credentials, handle 2FA

Customizing Sessions

Extending JWT & Session Callbacks

  1. Define callbacks for session and JWT

    callbacks: {
      async jwt(token, user) {
        // Extend token with custom properties
      },
      async session(session, token) {
        // Extend session properties
      }
    };
    
  2. Use custom user properties in the extended session

Error Handling

Display Custom Errors in UI

  • Create custom error & success components
  • Display them conditionally

Protected Routes and Middleware

Setting Up Middleware

  1. Add middleware file in root
  2. Customize with regular expressions to handle public and protected routes
export { nextAuthMiddleware } from "@auth/core";
export const config = {
  matcher: ["/*"]; // Or custom matcher
};

2FA and Email Verification

Implementing Two-Factor Authentication

  • Read OTP from DB, validate it, and delete once used

Implementing Email Verification

  • Send verification email, read token from URL, verify user email in DB

Custom Hooks and Utilities

Creating Custom Hooks for OAuth

export const useCurrentUser = () => {
  const { data: session } = useSession();
  return session?.user || null;
};
  • Use hooks to get the current user/session properties

Admin-Only Components and Routes

Creating Admin Components

  • Use role-checking to restrict access to certain routes or components
const AdminComponent = ({ children }) => {
  const role = useCurrentUserRole();
  if (role !== 'admin') return null;
  return children;
};

Deploying the Project

Deployment Steps

  • Push project to GitHub
  • Use Vercel for deployment

Additional Setup

  • Update environment variables on Vercel
  • Integrate email provider (e.g., Resend)

Summary

Overall Learnings

  • Set up authentication with NextAuth.js
  • User role management
  • Implement 2FA
  • Protect routes with middlewares
  • Utilize custom hooks for session management