Authentication
Secure user authentication with Auth.js v5, Google OAuth, and Supabase user sync.
shipsaas uses Auth.js v5 (NextAuth) with Google OAuth pre-configured. Users are automatically synced to your Supabase database on first sign-in.
Configuration
Environment Variables
Add the following to your .env.local file:
# Generate a secret: openssl rand -base64 32
AUTH_SECRET=your-auth-secret-here
# Google OAuth (https://console.developers.google.com/)
AUTH_GOOGLE_ID=your-google-client-id
AUTH_GOOGLE_SECRET=your-google-client-secretGenerate a secure secret: Run openssl rand -base64 32 in your terminal to generate a random secret key.
Auth.js Configuration
Authentication is configured in lib/auth.js. It exports auth, signIn, signOut, and handlers.
lib/auth.js
Auth.js v5 configuration with Google OAuth, Supabase user sync, and session callbacks.
import NextAuth from "next-auth";
import Google from "next-auth/providers/google";
import supabase from "./supabase";
// User helpers — auto-create users in Supabase on first sign-in
async function getUser(email) {
const { data } = await supabase
.from("users")
.select("*")
.eq("email", email)
.single();
return data;
}
async function createUser(newUser) {
const { data, error } = await supabase.from("users").insert([newUser]);
if (error) throw new Error("User could not be created");
return data;
}
const authConfig = {
providers: [
Google({
clientId: process.env.AUTH_GOOGLE_ID,
clientSecret: process.env.AUTH_GOOGLE_SECRET,
}),
// TODO: Add more providers (GitHub, Discord, etc.)
],
callbacks: {
authorized({ auth }) {
return !!auth?.user;
},
async signIn({ user }) {
const existingUser = await getUser(user.email);
if (!existingUser) {
await createUser({ email: user.email, full_name: user.name });
}
return true;
},
async session({ session }) {
const dbUser = await getUser(session.user.email);
if (dbUser) session.user.id = dbUser.id;
return session;
},
},
pages: { signIn: "/login" },
};
export const { auth, signIn, signOut, handlers } = NextAuth(authConfig);Route Handler
The Auth.js route handler lives at app/api/auth/[...nextauth]/route.ts:
import { handlers } from "@/lib/auth";
export const { GET, POST } = handlers;Usage
Server-Side Authentication
Protect server components by importing auth from lib/auth:
import { auth } from "@/lib/auth";
import { redirect } from "next/navigation";
export default async function ProtectedPage() {
const session = await auth();
if (!session?.user) {
redirect("/login");
}
return (
<div>
<h1>Welcome, {session.user.name}</h1>
<p>Email: {session.user.email}</p>
</div>
);
}Client-Side Sign In / Sign Out
Use the signIn and signOut functions from next-auth/react:
"use client";
import { signIn, signOut } from "next-auth/react";
// Sign in with Google
<button onClick={() => signIn("google")}>
Sign in with Google
</button>
// Sign out
<button onClick={() => signOut()}>
Sign Out
</button>OAuth Providers
To set up Google OAuth:
- Go to Google Cloud Console
- Create a new project or select an existing one
- Enable Google+ API
- Create OAuth 2.0 credentials
- Add authorized redirect URI:
http://localhost:3000/api/auth/callback/google - Copy Client ID and Secret to
AUTH_GOOGLE_IDandAUTH_GOOGLE_SECRETin.env.local
Adding More Providers
Add providers in lib/auth.js:
import GitHub from "next-auth/providers/github";
import Discord from "next-auth/providers/discord";
providers: [
Google({ ... }),
GitHub({
clientId: process.env.AUTH_GITHUB_ID,
clientSecret: process.env.AUTH_GITHUB_SECRET,
}),
Discord({
clientId: process.env.AUTH_DISCORD_ID,
clientSecret: process.env.AUTH_DISCORD_SECRET,
}),
]✓ You're all set! Authentication is configured with automatic Supabase user sync. Next, configure database integration to customize your user schema.