Chameleon

Authentication

User authentication and authorization system

Authentication

Chameleon uses NextAuth.js v5 for secure user authentication with OAuth providers and session management.

Overview

The authentication system provides secure user login through OAuth providers (Google and GitHub), session management, and protected route access. Users can sign in with their existing accounts without creating new passwords, and the system automatically handles user registration and profile management.

Setup

Environment Variables

Configure authentication in your environment:

# Google OAuth
NEXT_PUBLIC_AUTH_GOOGLE_ENABLED=true
NEXT_PUBLIC_AUTH_GOOGLE_ID="your-google-client-id"
AUTH_GOOGLE_ID="your-google-client-id"
AUTH_GOOGLE_SECRET="your-google-client-secret"
NEXT_PUBLIC_AUTH_GOOGLE_ONE_TAP_ENABLED=true

# GitHub OAuth
NEXT_PUBLIC_AUTH_GITHUB_ENABLED=true
AUTH_GITHUB_ID="your-github-client-id"
AUTH_GITHUB_SECRET="your-github-client-secret"

# NextAuth Configuration
NEXTAUTH_SECRET="your-random-secret-key"
AUTH_SECRET="your-random-secret-key"
NEXTAUTH_URL="http://localhost:3000"

OAuth Provider Setup

Google OAuth:

  1. Go to Google Cloud Console
  2. Create OAuth 2.0 credentials
  3. Add authorized redirect URIs:
    • http://localhost:3000/api/auth/callback/google (development)
    • https://your-domain.com/api/auth/callback/google (production)

GitHub OAuth:

  1. Go to GitHub Settings > Developer settings
  2. Create new OAuth App
  3. Set Authorization callback URL:
    • http://localhost:3000/api/auth/callback/github (development)
    • https://your-domain.com/api/auth/callback/github (production)

Usage

Sign In Component

// src/components/auth/sign-in-button.tsx
import { signIn } from "next-auth/react";

export function SignInButton() {
  return (
    <button onClick={() => signIn("google")}>
      Sign in with Google
    </button>
  );
}

Protected Routes

// src/app/dashboard/page.tsx
import { auth } from "@/auth";
import { redirect } from "next/navigation";

export default async function DashboardPage() {
  const session = await auth();
  
  if (!session) {
    redirect("/auth/signin");
  }
  
  return <div>Welcome, {session.user.name}!</div>;
}

Session Access

// Client component
import { useSession } from "next-auth/react";

export function UserProfile() {
  const { data: session, status } = useSession();
  
  if (status === "loading") return <p>Loading...</p>;
  if (status === "unauthenticated") return <p>Not signed in</p>;
  
  return <p>Signed in as {session?.user?.email}</p>;
}

File Locations

  • src/auth/config.ts - NextAuth configuration and providers
  • src/auth/handler.ts - User sign-in handling logic
  • src/auth/index.ts - NextAuth exports (handlers, signIn, signOut, auth)
  • src/auth/session.tsx - Session provider component
  • src/app/api/auth/[...nextauth]/route.ts - NextAuth API route

Common Tasks

Check Authentication Status

import { auth } from "@/auth";

const session = await auth();
if (session) {
  console.log("User is authenticated:", session.user.email);
}

Get User Information

const session = await auth();
const user = session?.user;
// user contains: uuid, email, nickname, avatar_url, created_at

Sign Out User

import { signOut } from "next-auth/react";

await signOut({ callbackUrl: "/" });

Admin Access Check

const adminEmails = process.env.ADMIN_EMAILS?.split(",");
const isAdmin = adminEmails?.includes(session?.user?.email);

Troubleshooting

"Invalid OAuth client" error

Problem: Google OAuth configuration incorrect

Solution:

  1. Check client ID and secret in environment variables
  2. Verify redirect URI matches exactly
  3. Ensure OAuth consent screen is configured

Session not persisting

Problem: User gets logged out frequently

Solution:

  1. Check NEXTAUTH_SECRET is set and consistent
  2. Verify NEXTAUTH_URL matches your domain
  3. Clear browser cookies and retry

Admin access denied

Problem: Can't access /admin even with admin email

Solution:

  1. Verify email is in ADMIN_EMAILS environment variable
  2. Check for typos in email address
  3. Restart server after changing ADMIN_EMAILS

Next Steps