Modern authentication with NextAuth.js v5 for Google Antigravity projects including OAuth, credentials, and session management.
# NextAuth.js v5 Authentication for Google Antigravity
Implement secure authentication with NextAuth.js v5 in your Google Antigravity IDE projects. This comprehensive guide covers OAuth providers, credentials authentication, and session management optimized for Gemini 3 agentic development.
## Auth Configuration
Set up NextAuth.js v5 with multiple providers:
```typescript
// auth.ts
import NextAuth from 'next-auth';
import { PrismaAdapter } from '@auth/prisma-adapter';
import GitHub from 'next-auth/providers/github';
import Google from 'next-auth/providers/google';
import Credentials from 'next-auth/providers/credentials';
import { prisma } from '@/lib/prisma';
import { compare } from 'bcryptjs';
import { z } from 'zod';
const credentialsSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
export const { handlers, signIn, signOut, auth } = NextAuth({
adapter: PrismaAdapter(prisma),
session: { strategy: 'jwt' },
pages: {
signIn: '/login',
error: '/auth/error',
},
providers: [
GitHub({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
profile(profile) {
return {
id: profile.id.toString(),
name: profile.name || profile.login,
email: profile.email,
image: profile.avatar_url,
role: 'user',
};
},
}),
Google({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
Credentials({
async authorize(credentials) {
const parsed = credentialsSchema.safeParse(credentials);
if (!parsed.success) return null;
const { email, password } = parsed.data;
const user = await prisma.user.findUnique({
where: { email },
select: {
id: true,
email: true,
name: true,
image: true,
password: true,
role: true,
},
});
if (!user || !user.password) return null;
const isValid = await compare(password, user.password);
if (!isValid) return null;
return {
id: user.id,
email: user.email,
name: user.name,
image: user.image,
role: user.role,
};
},
}),
],
callbacks: {
async jwt({ token, user }) {
if (user) {
token.id = user.id;
token.role = user.role;
}
return token;
},
async session({ session, token }) {
if (token) {
session.user.id = token.id as string;
session.user.role = token.role as string;
}
return session;
},
},
});
declare module 'next-auth' {
interface User {
role: string;
}
interface Session {
user: User & { id: string; role: string };
}
}
```
## API Routes
Set up auth handlers:
```typescript
// app/api/auth/[...nextauth]/route.ts
import { handlers } from '@/auth';
export const { GET, POST } = handlers;
```
## Middleware Protection
Protect routes with middleware:
```typescript
// middleware.ts
import { auth } from '@/auth';
import { NextResponse } from 'next/server';
const publicRoutes = ['/', '/login', '/register', '/prompts'];
const authRoutes = ['/login', '/register'];
const adminRoutes = ['/admin'];
export default auth((req) => {
const { nextUrl, auth } = req;
const isLoggedIn = !!auth;
const pathname = nextUrl.pathname;
const isPublicRoute = publicRoutes.some(
(route) => pathname === route || pathname.startsWith(`${route}/`)
);
const isAuthRoute = authRoutes.some((route) => pathname.startsWith(route));
const isAdminRoute = adminRoutes.some((route) => pathname.startsWith(route));
if (isAuthRoute && isLoggedIn) {
return NextResponse.redirect(new URL('/dashboard', nextUrl));
}
if (!isPublicRoute && !isLoggedIn) {
return NextResponse.redirect(new URL('/login', nextUrl));
}
if (isAdminRoute && auth?.user?.role !== 'admin') {
return NextResponse.redirect(new URL('/', nextUrl));
}
return NextResponse.next();
});
export const config = {
matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)' ],
};
```
## Server Components
Use auth in server components:
```typescript
// app/dashboard/page.tsx
import { auth } from '@/auth';
import { redirect } from 'next/navigation';
export default async function DashboardPage() {
const session = await auth();
if (!session?.user) {
redirect('/login');
}
return (
<div className="dashboard">
<h1>Welcome, {session.user.name}</h1>
<p>Role: {session.user.role}</p>
</div>
);
}
```
## Client Components
Use auth in client components:
```typescript
// components/UserMenu.tsx
'use client';
import { useSession, signIn, signOut } from 'next-auth/react';
export function UserMenu() {
const { data: session, status } = useSession();
if (status === 'loading') {
return <div className="skeleton" />;
}
if (!session) {
return <button onClick={() => signIn()}>Sign In</button>;
}
return (
<div className="user-menu">
<img src={session.user.image || '/avatar.png'} alt="" />
<span>{session.user.name}</span>
<button onClick={() => signOut()}>Sign Out</button>
</div>
);
}
```
## Best Practices
1. **Use JWT strategy** for serverless deployments
2. **Extend types** with declaration merging
3. **Implement middleware** for route protection
4. **Use server components** for auth checks
5. **Handle loading states** in client components
6. **Validate credentials** with Zod schemas
7. **Set up callbacks** for custom user propertiesThis nextauth prompt is ideal for developers working on:
By using this prompt, you can save hours of manual coding and ensure best practices are followed from the start. It's particularly valuable for teams looking to maintain consistency across their nextauth implementations.
Yes! All prompts on Antigravity AI Directory are free to use for both personal and commercial projects. No attribution required, though it's always appreciated.
This prompt works excellently with Claude, ChatGPT, Cursor, GitHub Copilot, and other modern AI coding assistants. For best results, use models with large context windows.
You can modify the prompt by adding specific requirements, constraints, or preferences. For nextauth projects, consider mentioning your framework version, coding style, and any specific libraries you're using.