I am trying to build a linked clone with next.js and despite everything being correct I am getting this OAuthCallback error after signing in with my credentials and I am getting redirected to home page instead of index page. Below are the codes for reference -
home.js -
import Image from "next/image";
import Head from "next/head";
import { useSession, signIn } from "next-auth/react";
import { useRouter } from "next/router";
import { useEffect } from "react";
import { getProviders } from "next-auth/react";
import linkdin_full from "../public/logos/linkdin_full.svg";
import linkdin_home from "../public/linkdin_home.svg";
import HeaderLink from "../components/HeaderLink.js";
import NewspaperIcon from "@mui/icons-material/Newspaper";
import PeopleIcon from "@mui/icons-material/People";
import OndemandVideoIcon from "@mui/icons-material/OndemandVideo";
import BusinessCenterIcon from "@mui/icons-material/BusinessCenter";
import ExtensionIcon from "@mui/icons-material/Extension";
import { SessionProvider } from "next-auth/react"; // ✅ Added SessionProvider
function HomePage({ providers }) {
return (
<SessionProvider>
<ActualHome providers={providers} />
</SessionProvider>
);
}
function ActualHome({ providers }) {
const { data: session, status } = useSession();
const router = useRouter();
const { error } = router.query;
useEffect(() => {
if (status === "authenticated") {
router.push("/");
}
}, [status, router]);
if (status === "loading") {
return <div>Loading...</div>;
}
return (
<div className="space-y-10 relative">
<Head>
<title>LinkdIn: Log In or Sign Up</title>
<link rel="icon" href="/logos/LinkdIn_Icon.png" />
</Head>
{error && (
<div className="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded mx-auto max-w-md mt-4">
<p>Authentication error: {error}</p>
<button
className="underline mt-2"
onClick={() => signIn("linkedin", { callbackUrl: "/" })}
>
Try again
</button>
</div>
)}
<header className="flex justify-around items-center py-4">
<div className="relative w-36 h-10">
<Image
src={linkdin_full}
alt="LinkedIn Full Logo"
fill
style={{ objectFit: "contain" }}
/>
</div>
<div className="flex items-center sm:divide-x divide-gray-300">
<div className="hidden sm:flex space-x-8 pr-4">
<HeaderLink Icon={NewspaperIcon} text="Articles" />
<HeaderLink Icon={PeopleIcon} text="People" />
<HeaderLink Icon={OndemandVideoIcon} text="Learning" />
<HeaderLink Icon={BusinessCenterIcon} text="Jobs" />
<HeaderLink Icon={ExtensionIcon} text="Games" />
</div>
<div className="space-x-4 px-2">
<button className="font-semibold text-gray-700 hover:bg-gray-100 px-6 py-3 rounded-full hover:text-gray-800">
Join now
</button>
{providers &&
Object.values(providers).map((provider) => (
<button
key={provider.id}
className="text-blue-600 font-semibold rounded-full border border-blue-600 px-6 py-3 transition-all hover:text-blue-900 hover:bg-blue-50"
onClick={() => signIn(provider.id, { callbackUrl: "/" })}
>
Sign in
</button>
))}
</div>
</div>
</header>
<main className="flex flex-col xl:flex-row items-center max-w-screen-lg mx-auto">
<div className="space-y-6 xl:space-y-10">
<h1 className="text-gray-700 text-3xl md:text-5xl max-w-xl !leading-snug pl-4 xl:pl-0">
Welcome to your professional community
</h1>
</div>
<div className="relative xl:absolute w-80 h-80 xl:w-[650px] xl:h-[650px] top-14 right-5">
<Image
src={linkdin_home}
alt="LinkedIn Home Image"
fill
style={{ objectFit: "cover" }}
priority
/>
</div>
</main>
</div>
);
}
export default HomePage;
export async function getServerSideProps() {
const providers = await getProviders();
return {
props: {
providers: providers || {}, // ✅ Ensure it doesn't crash if providers is undefined
},
};
}
index.js -
import { useSession } from "next-auth/react";
import { useRouter } from "next/router";
import { useEffect } from "react";
import { Geist, Geist_Mono } from "next/font/google";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
export default function Index() {
const { data: session, status } = useSession();
const router = useRouter();
useEffect(() => {
// If user is not authenticated, redirect to home page
if (status === "unauthenticated") {
router.push("/home");
}
}, [status, router]);
// Show loading state while checking authentication
if (status === "loading") {
return <div>Loading...</div>;
}
// Show main content if authenticated
return (
<div className={`${geistSans.variable} ${geistMono.variable}`}>
<h1>Welcome to LinkedIn</h1>
{session && (
<div>
<p>You are logged in as: {session.user.name}</p>
{/* Your authenticated content here */}
</div>
)}
</div>
);
}
[...nextauth].js -
import NextAuth from "next-auth";
import LinkedInProvider from "next-auth/providers/linkedin";
import { MongoDBAdapter } from "@next-auth/mongodb-adapter";
import clientPromise from "@/lib/mongodb";
export default NextAuth({
providers: [
LinkedInProvider({
clientId: process.env.LINKEDIN_CLIENT_ID,
clientSecret: process.env.LINKEDIN_CLIENT_SECRET,
authorization: {
params: {
scope: "profile email openid", // Updated to newer LinkedIn OAuth 2.0 scopes
},
},
profile(profile) {
return {
id: profile.sub,
name: profile.name,
email: profile.email,
image: profile.picture,
};
},
}),
],
secret: process.env.NEXTAUTH_SECRET,
adapter: MongoDBAdapter(clientPromise),
pages: {
signIn: "/home",
},
debug: process.env.NODE_ENV === "development", // Add debug mode for development
callbacks: {
async redirect({ url, baseUrl }) {
// Handle callbackUrl properly to ensure redirection to index after login
if (url.startsWith(baseUrl)) return url;
// Make sure we redirect to index.js after successful login
return baseUrl;
},
async session({ session, token, user }) {
if (session.user) {
session.user.id = token.sub || user?.id;
}
return session;
},
async jwt({ token, user }) {
if (user) {
token.id = user.id;
}
return token;
},
},
session: {
strategy: "jwt",
},
});
also i have configured the .env.local file with all the necessary stuff so there's not problem in that and it's working with the google provider oauth but not with linkedin oauth