Social login reduces friction during signup. Here is how to add Google, GitHub, and more with Auth.js (NextAuth v5).
Step 1: Install Auth.js
pnpm add next-auth@beta @auth/drizzle-adapter
Step 2: Get OAuth Credentials
- Go to Google Cloud Console
- Create a new project
- Go to APIs & Services > Credentials
- Create OAuth 2.0 Client ID
- Set authorized redirect URI to
http://localhost:3000/api/auth/callback/google
GitHub
- Go to Settings > Developer Settings > OAuth Apps
- Create a new OAuth App
- Set callback URL to
http://localhost:3000/api/auth/callback/github
AUTH_SECRET=your_random_secret
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret
Step 3: Auth Configuration
// auth.ts
import NextAuth from "next-auth";
import Google from "next-auth/providers/google";
import GitHub from "next-auth/providers/github";
import { DrizzleAdapter } from "@auth/drizzle-adapter";
import { db } from "@/db";
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: DrizzleAdapter(db),
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!,
}),
],
pages: {
signIn: "/login",
error: "/login",
},
callbacks: {
async session({ session, user }) {
session.user.id = user.id;
return session;
},
},
});
Step 4: Route Handler
// app/api/auth/[...nextauth]/route.ts
import { handlers } from "@/auth";
export const { GET, POST } = handlers;
Step 5: Middleware for Protected Routes
// middleware.ts
import { auth } from "@/auth";
export default auth((req) => {
if (!req.auth && req.nextUrl.pathname.startsWith("/dashboard")) {
const loginUrl = new URL("/login", req.nextUrl.origin);
loginUrl.searchParams.set("callbackUrl", req.nextUrl.pathname);
return Response.redirect(loginUrl);
}
});
export const config = {
matcher: ["/dashboard/:path*", "/settings/:path*"],
};
Step 6: Login Page
// app/login/page.tsx
import { auth, signIn } from "@/auth";
import { redirect } from "next/navigation";
export default async function LoginPage({
searchParams,
}: {
searchParams: Promise<{ callbackUrl?: string; error?: string }>;
}) {
const session = await auth();
const { callbackUrl, error } = await searchParams;
if (session) redirect(callbackUrl || "/dashboard");
return (
<main className="flex min-h-screen items-center justify-center">
<div className="w-full max-w-sm rounded-2xl border p-8 dark:border-gray-700">
<h1 className="text-center text-2xl font-bold">Welcome Back</h1>
<p className="mt-2 text-center text-sm text-gray-500">
Sign in to your account
</p>
{error && (
<div className="mt-4 rounded-lg bg-red-50 p-3 text-sm text-red-600 dark:bg-red-950 dark:text-red-400">
{error === "OAuthAccountNotLinked"
? "This email is already associated with another account."
: "An error occurred. Please try again."}
</div>
)}
<div className="mt-6 space-y-3">
<form
action={async () => {
"use server";
await signIn("google", { redirectTo: callbackUrl || "/dashboard" });
}}
>
<button
type="submit"
className="flex w-full items-center justify-center gap-3 rounded-lg border bg-white px-4 py-2.5 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700"
>
<GoogleIcon />
Continue with Google
</button>
</form>
<form
action={async () => {
"use server";
await signIn("github", { redirectTo: callbackUrl || "/dashboard" });
}}
>
<button
type="submit"
className="flex w-full items-center justify-center gap-3 rounded-lg border bg-gray-900 px-4 py-2.5 text-sm font-medium text-white hover:bg-gray-800"
>
<GitHubIcon />
Continue with GitHub
</button>
</form>
</div>
<p className="mt-6 text-center text-xs text-gray-500">
By signing in, you agree to our Terms and Privacy Policy.
</p>
</div>
</main>
);
}
function GoogleIcon() {
return (
<svg className="h-5 w-5" viewBox="0 0 24 24">
<path
fill="#4285F4"
d="M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92a5.06 5.06 0 0 1-2.2 3.32v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.1z"
/>
<path
fill="#34A853"
d="M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23z"
/>
<path
fill="#FBBC05"
d="M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22.81-.62z"
/>
<path
fill="#EA4335"
d="M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53z"
/>
</svg>
);
}
function GitHubIcon() {
return (
<svg className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
</svg>
);
}
Step 7: User Session in Components
// Server Component
import { auth } from "@/auth";
export default async function Dashboard() {
const session = await auth();
return <p>Welcome, {session?.user?.name}</p>;
}
// Client Component
"use client";
import { useSession } from "next-auth/react";
export function UserMenu() {
const { data: session } = useSession();
if (!session) return <a href="/login">Sign in</a>;
return (
<div className="flex items-center gap-2">
<img
src={session.user?.image || ""}
alt=""
className="h-8 w-8 rounded-full"
/>
<span className="text-sm">{session.user?.name}</span>
</div>
);
}
Need Authentication for Your App?
We build web applications with secure authentication, social login, and user management. Contact us to discuss your project.