Skip to main content

authjs-skills

Auth.js v5 setup for Next.js authentication including Google OAuth, credentials provider, environment configuration, and core API integration

الانتقال إلى التثبيت

معلومات المصدر

المستودع
gocallum/nextjs16-agent-skills
آخر نشاط في المصدر
١٩ يناير ٢٠٢٦ في ١٠:١٧
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٢٣
التفرعات
٧

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
authjs-skills
description
Auth.js v5 setup for Next.js authentication including Google OAuth, credentials provider, environment configuration, and core API integration
## Links - Getting Started: https://authjs.dev/getting-started/installation?framework=Next.js - Migrating to v5: https://authjs.dev/getting-started/migrating-to-v5 - Google Provider: https://authjs.dev/getting-started/providers/google - Credentials Provider: https://authjs.dev/getting-started/providers/credentials - Core API Reference: https://authjs.dev/reference/core - Session Management: https://authjs.dev/getting-started/session-management - Concepts: https://authjs.dev/concepts ## Installation ```sh pnpm add next-auth@beta ``` **Note**: Auth.js v5 is currently in beta. Use `next-auth@beta` to install the latest v5 version. ## What's New in Auth.js v5? ### Key Changes from v4 - **Simplified Configuration**: More streamlined setup with better TypeScript support - **Universal `auth()` Export**: Single function for authentication across all contexts - **Enhanced Security**: Improved CSRF protection and session handling - **Edge Runtime Support**: Full compatibility with Edge Runtime and middleware - **Better Type Safety**: Improved TypeScript definitions throughout ## Environment Variables ### Required Environment Variables ```env # Auth.js Configuration AUTH_SECRET=your_secret_key_here # Google OAuth (if using Google provider) AUTH_GOOGLE_ID=your_google_client_id AUTH_GOOGLE_SECRET=your_google_client_secret # For production deployments AUTH_URL=https://yourdomain.com # For development (optional, defaults to http://localhost:3000) # AUTH_URL=http://localhost:3000 ``` ### Generating AUTH_SECRET ```sh # Generate a random secret (Unix/Linux/macOS) openssl rand -base64 32 # Alternative using Node.js node -e "console.log(require('crypto').randomBytes(32).toString('base64'))" # Using pnpm pnpm dlx auth secret ``` **Important**: Never commit `AUTH_SECRET` to version control. Use `.env.local` for development. ## Basic Setup (Next.js App Router) ### 1. Create `auth.ts` Configuration File Create `auth.ts` at the project root (next to `package.json`): ```typescript import NextAuth from "next-auth" import Google from "next-auth/providers/google" import Credentials from "next-auth/providers/credentials" export const { handlers, signIn, signOut, auth } = NextAuth({ providers: [ Google({ clientId: process.env.AUTH_GOOGLE_ID, clientSecret: process.env.AUTH_GOOGLE_SECRET, }), Credentials({ credentials: { email: { label: "Email", type: "email" }, password: { label: "Password", type: "password" }, }, authorize: async (credentials) => { // TODO: Implement your authentication logic here // This is a basic example - see Credentials Provider section below for complete implementation if (!credentials?.email || !credentials?.password) { return null } // Example: validate against database (placeholder) // See "Credentials Provider" section for full implementation with bcrypt const user = { id: "1", email: credentials.email, name: "User" } // Replace with actual DB lookup if (!user) { return null } return { id: user.id, email: user.email, name: user.name, } }, }), ], pages: { signIn: '/auth/signin', }, callbacks: { authorized: async ({ auth }) => { // Return true if user is authenticated return !!auth }, }, }) ``` **Note**: This is a basic setup example. For production-ready credentials authentication, see the "Credentials Provider" section below which includes proper password hashing with bcrypt and database integration. ### 2. Create API Route Handler Create `app/api/auth/[...nextauth]/route.ts`: ```typescript import { handlers } from "@/auth" export const { GET, POST } = handlers ``` ### 3. Add Middleware (Optional but Recommended) Create `middleware.ts` at the project root: ```typescript export { auth as middleware } from "@/auth" export const config = { matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"], } ``` For more control: ```typescript import { auth } from "@/auth" export default auth((req) => { const isLoggedIn = !!req.auth const isOnDashboard = req.nextUrl.pathname.startsWith('/dashboard') if (isOnDashboard && !isLoggedIn) { return Response.redirect(new URL('/auth/signin', req.url)) } }) export const config = { matcher: ['/dashboard/:path*', '/profile/:path*'], } ``` ## Google OAuth Provider ### 1. Google Cloud Console Setup 1. Go to [Google Cloud Console](https://console.cloud.google.com/) 2. Create a new project or select existing 3. Enable Google+ API 4. Create OAuth 2.0 credentials: - Application type: Web application - Authorized redirect URIs: - Development: `http://localhost:3000/api/auth/callback/google` - Production: `https://yourdomain.com/api/auth/callback/google` 5. Copy Client ID and Client Secret to `.env.local` ### 2. Configuration ```typescript import NextAuth from "next-auth" import Google from "next-auth/providers/google" export const { handlers, signIn, signOut, auth } = NextAuth({ providers: [ Google({ clientId: process.env.AUTH_GOOGLE_ID, clientSecret: process.env.AUTH_GOOGLE_SECRET, authorization: { params: { prompt: "consent", access_type: "offline", response_type: "code" } } }), ], }) ``` ### 3. Google Provider Options ```typescript Google({ clientId: process.env.AUTH_GOOGLE_ID, clientSecret: process.env.AUTH_GOOGLE_SECRET, // Request additional scopes authorization: { params: { scope: "openid email profile", prompt: "select_account", // Force account selection } }, // Allow specific domains only allowDangerousEmailAccountLinking: false, }) ``` ## Credentials Provider (Username/Password) ### Required Dependencies ```sh # Install required packages for credentials provider pnpm add bcryptjs zod pnpm add -D @types/bcryptjs ``` ### 1. Basic Configuration ```typescript import NextAuth from "next-auth" import Credentials from "next-auth/providers/credentials" import { z } from "zod" import bcrypt from "bcryptjs" import { prisma } from "@/lib/prisma" const credentialsSchema = z.object({ email: z.string().email(), password: z.string().min(8), }) export const { handlers, signIn, signOut, auth } = NextAuth({ providers: [ Credentials({ credentials: { email: { label: "Email", type: "email", placeholder: "user@example.com" }, password: { label: "Password", type: "password" }, }, authorize: async (credentials) => { try { const { email, password } = credentialsSchema.parse(credentials) // Fetch user from database const user = await prisma.user.findUnique({ where: { email }, }) if (!user) { throw new Error("User not found") } // Verify password const isValidPassword = await bcrypt.compare(password, user.hashedPassword) if (!isValidPassword) { throw new Error("Invalid password") } // Return user object (must include id) return { id: user.id, email: user.email, name: user.name, image: user.image, } } catch (error) { console.error("Authentication error:", error) return null } }, }), ], session: { strategy: "jwt", // Required for credentials provider }, }) ``` ### 2. User Registration Example ```typescript // app/api/auth/register/route.ts import { NextResponse } from "next/server" import bcrypt from "bcryptjs" import { z } from "zod" import { prisma } from "@/lib/prisma" const registerSchema = z.object({ email: z.string().email(), password: z.string().min(8), name: z.string().min(2), }) export async function POST(req: Request) { try { const body = await req.json() const { email, password, name } = registerSchema.parse(body) // Check if user exists const existingUser = await prisma.user.findUnique({ where: { email }, }) if (existingUser) { return NextResponse.json( { error: "User already exists" }, { status: 400 } ) } // Hash password const hashedPassword = await bcrypt.hash(password, 10) // Create user const user = await prisma.user.create({ data: { email, name, hashedPassword, }, }) return NextResponse.json( { message: "User created successfully", userId: user.id }, { status: 201 } ) } catch (error) { console.error("Registration error:", error) return NextResponse.json( { error: "Failed to register user" }, { status: 500 } ) } } ``` ## Using Auth in Components ### Server Components ```typescript import { auth } from "@/auth" export default async function ProfilePage() { const session = await auth() if (!session?.user) { return <div>Not authenticated</div> } return ( <div> <h1>Welcome, {session.user.name}!</h1> <p>Email: {session.user.email}</p> </div> ) } ``` ### Server Actions ```typescript "use server" import { auth } from "@/auth" import { revalidatePath } from "next/cache" import { prisma } from "@/lib/prisma" export async function updateProfile(formData: FormData) { const session = await auth() if (!session?.user) { throw new Error("Not authenticated") } const name = formData.get("name") as string // Update database await prisma.user.update({ where: { id: session.user.id }, data: { name }, }) revalidatePath("/profile") } ``` ### Client Components (with SessionProvider) ```typescript // app/providers.tsx "use client" import { SessionProvider } from "next-auth/react" export function Providers({ children }: { children: React.ReactNode }) { return <SessionProvider>{children}</SessionProvider> } ``` ```typescript // app/layout.tsx import { Providers } from "./providers" export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( <html lang="en"> <body> <Providers>{children}</Providers> </body> </html> ) } ``` ```typescript // app/components/user-profile.tsx "use client" import { useSession, signIn, signOut } from "next-auth/react" export function UserProfile() { const { data: session, status } = useSession() if (status === "loading") { return <div>Loading...</div> } if (!session) { return ( <button onClick={() => signIn()}> Sign In </button> ) } return ( <div> <p>Signed in as {session.user?.email}</p> <button onClick={() => signOut()}> Sign Out </button> </div> ) } ``` ## Sign In/Out Actions ### Programmatic Sign In ```typescript import { signIn } from "@/auth" // Server Action export async function handleSignIn(provider: string) { "use server" await signIn(provider) }
عرض على GitHub
ملف SKILL.md هذا كبير جدا، لذلك يعرض SkillsMP القسم الاول فقط هنا. عرض على GitHub