I am trying to implement Next-Auth on latest NextJS 13 with a strapi backend. However, most of the documentations that are available are either stale or do not capture the use of Google as a provider. I have fumbled around but nothing seems to bear fruits. Here is my implementation so far. My code is using TypeScript:
I created a route.ts file in: app/api/auth/[...nextauth]
with the following content:
import NextAuth from 'next-auth';
import GoogleProvider from "next-auth/providers/google";
const handler = NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string
})
],
callbacks: {
async session({ user, session, token }) {
session.user = token as any;
session.user.id = user ? user.id : null;
return Promise.resolve(session);
},
async jwt({ token, user, account }) {
const isSignIn = user ? true : false;
if (isSignIn && account) {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/api/auth/${account.provider}/callback?access_token=${account?.accessToken}`
);
const data = await response.json();
token.jwt = data.jwt;
token.id = data.user.id;
}
return Promise.resolve(token);
},
},
secret: process.env.NEXTAUTH_SECRET as string
});
export { handler as GET, handler as POST };
So, the login and logout works fine with the code, but the problem comes when I try to link this to Strapi
. The thing is, I don't really know what is to be done. Some docs talk of first calling the database and saving the data before fetching the access token from strapi, for example: User Authentication in Next.js with Strapi. However, the documentation appears to be stale as Next-Auth recommends using adapters for database. But there is no place where this is described for Strapi as most docs on using adapters suggest creating of new models.
So, my main problem is, how do I persist this logged in user to Strapi database after successful login?
How do I get the access token from Strapi for subsequent API calls that need authentication?
A pointer to a working code/docs/example will help alot.
I finally got a workaround this. First of all, I had to put the fetch request in the jwt callback in a try catch block so that I could get what error was affecting it. Also, after a long debugging, I realized that the accessToken
from the Google Account object is actually written as access_token
and not accessToken
as most documentation put it. Here is the working code after making the changes:
import NextAuth from 'next-auth';
import GoogleProvider from "next-auth/providers/google";
const handler = NextAuth({
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string
})
],
session: { strategy: "jwt" },
callbacks: {
async session({ user, session, token }) {
session.user = token as any;
session.user.id = user ? user.id : null;
return Promise.resolve(session);
},
async jwt({ token, user, account }) {
const isSignIn = user ? true : false;
if (isSignIn && account) {
try {
console.log("Google Account >>>>>>>>>>>>>> ", account);
const public_url = process.env.NEXT_PUBLIC_API_URL;
const response = await fetch(
`${public_url}/api/auth/${account.provider}/callback?access_token=${account?.access_token}`
);
const data = await response.json();
console.log("Strapi Callback Data >>>>>>>>>>>>>> ", data);
token.jwt = data.jwt;
token.id = data.user.id;
} catch (error) {
console.error('Fetch failed:', error);
}
}
return Promise.resolve(token);
},
},
secret: process.env.NEXTAUTH_SECRET as string
});
export { handler as GET, handler as POST };
I hope it helps others who are having the same problem as I had.
On a side note, I had to use 127.0.0.1:1337
instead of localhost:1337
as the latter gave me connection error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With