Complete guide to NextAuth v5, OAuth providers, and role-based access control in NextReady.
// auth.config.ts
import type { NextAuthConfig } from "next-auth";
import Google from "next-auth/providers/google";
import GitHub from "next-auth/providers/github";
import Credentials from "next-auth/providers/credentials";
import { signInSchema } from "@/lib/validations";
export const authConfig = {
providers: [
Google({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
GitHub({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
}),
Credentials({
async authorize(credentials) {
const validatedFields = signInSchema.safeParse(credentials);
if (validatedFields.success) {
const { email, password } = validatedFields.data;
const user = await getUserByEmail(email);
if (!user || !user.password) return null;
const passwordsMatch = await bcrypt.compare(password, user.password);
if (passwordsMatch) return user;
}
return null;
},
}),
],
pages: {
signIn: "/signin",
signUp: "/signup",
},
callbacks: {
authorized({ auth, request: { nextUrl } }) {
const isLoggedIn = !!auth?.user;
const isOnDashboard = nextUrl.pathname.startsWith('/dashboard');
if (isOnDashboard) {
if (isLoggedIn) return true;
return false; // Redirect to login page
} else if (isLoggedIn) {
return Response.redirect(new URL('/dashboard', nextUrl));
}
return true;
},
},
} satisfies NextAuthConfig;// lib/permissions.ts
export enum UserRole {
USER = "USER",
ADMIN = "ADMIN",
SUPER_ADMIN = "SUPER_ADMIN"
}
export enum Permission {
USER_READ = "USER_READ",
USER_WRITE = "USER_WRITE",
USER_DELETE = "USER_DELETE",
FILE_UPLOAD = "FILE_UPLOAD",
EMAIL_SEND = "EMAIL_SEND",
ADMIN_PANEL = "ADMIN_PANEL"
}
const rolePermissions: Record<UserRole, Permission[]> = {
[UserRole.USER]: [
Permission.USER_READ,
Permission.FILE_UPLOAD
],
[UserRole.ADMIN]: [
Permission.USER_READ,
Permission.USER_WRITE,
Permission.FILE_UPLOAD,
Permission.EMAIL_SEND,
Permission.ADMIN_PANEL
],
[UserRole.SUPER_ADMIN]: Object.values(Permission)
};
export class PermissionChecker {
static hasRole(user: User, requiredRole: UserRole): boolean {
const roleHierarchy = {
[UserRole.SUPER_ADMIN]: 3,
[UserRole.ADMIN]: 2,
[UserRole.USER]: 1
};
return roleHierarchy[user.role] >= roleHierarchy[requiredRole];
}
static hasPermission(user: User, permission: Permission): boolean {
const userPermissions = rolePermissions[user.role] || [];
return userPermissions.includes(permission);
}
}// components/auth/ProtectedRoute.tsx
import { useSession } from "next-auth/react";
import { UserRole, Permission } from "@/lib/permissions";
import { PermissionChecker } from "@/lib/permissions";
interface ProtectedRouteProps {
requiredRole?: UserRole;
requiredPermission?: Permission;
children: React.ReactNode;
fallback?: React.ReactNode;
}
export function ProtectedRoute({
requiredRole,
requiredPermission,
children,
fallback = <AccessDenied />
}: ProtectedRouteProps) {
const { data: session, status } = useSession();
if (status === "loading") {
return <LoadingSpinner />;
}
if (!session) {
return <SignInPrompt />;
}
if (requiredRole && !PermissionChecker.hasRole(session.user, requiredRole)) {
return fallback;
}
if (requiredPermission && !PermissionChecker.hasPermission(session.user, requiredPermission)) {
return fallback;
}
return <>{children}</>;
}
// Usage example
<ProtectedRoute requiredRole={UserRole.ADMIN}>
<AdminDashboard />
</ProtectedRoute>// API route with protection
import { withApiMiddleware } from "@/lib/api-middleware";
import { UserRole, Permission } from "@/lib/permissions";
async function handler(request: NextRequest) {
// Your API logic here
const users = await db.user.findMany();
return Response.json(users);
}
export const GET = withApiMiddleware(handler, {
rateLimit: "default",
requiredRole: UserRole.ADMIN,
requiredPermission: Permission.USER_READ,
});1. Create Google Cloud Project
Go to Google Cloud Console and create a new project
2. Enable Google+ API
Enable the Google+ API in your project
3. Create OAuth Credentials
Create OAuth 2.0 client credentials for web application
4. Configure Redirect URLs
Add your callback URLs (e.g., http://localhost:3000/api/auth/callback/google)
1. Register OAuth App
Go to Settings → Developer settings → OAuth Apps
2. Configure Application
Set homepage URL and authorization callback URL
3. Get Credentials
Copy Client ID and generate Client Secret
4. Add to Environment
Add GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET to .env.local
Try signing in with Google and GitHub to ensure OAuth is configured correctly
Test that admin-only pages are properly protected from regular users
Ensure sessions persist across browser refreshes and tabs
Your authentication system is now configured. Ready to learn about other NextReady systems?