I am currently working on a project that uses Next.js with next-auth for the frontend and Python FastAPI for the backend. I have been using the Google provider for authentication, and I plan to add a magic link login in the future. I'm utilizing the database strategy with the MongoDB adapter for handling user data.
While I have a good understanding of the frontend implementation, I'm having trouble figuring out the best way to validate the user on the backend.
My current approach is to use the next-auth.session-token from the cookies and send this token to the backend. In the backend, I validate whether the token is legitimate, determine the user associated with the token, and check if the token has expired. To do this, I query the sessions collection in the MongoDB database created by next-auth using the next-auth.session-token and access the user information, including their role.
However, I am concerned about the security of this approach. If the database were to be compromised, an attacker could potentially gain access to all user login tokens and misuse them. This seems very insecure, and I couldn't find much information in the next-auth documentation about this topic.
Another issue I'm facing is that since the next-auth.session-token cookie can only be accessed by the backend, I have to route all requests to the backend from my client through a proxy to add the next-auth.session-token to the request. This doesn't seem like the right way to handle this.
I am wondering if there's a better and more secure way to handle authentication and authorization between my Next.js frontend and FastAPI backend using the MongoDB adapter. Any guidance, resources or best practices for enhancing security and improving the architecture would be greatly appreciated.
My setup in[...nextauth].ts looks like this:
import NextAuth from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';
import clientPromise from '../../../utils/mongodb/mongodb';
import { MongoDBAdapter } from '@next-auth/mongodb-adapter';
export default NextAuth({
// Configure one or more authentication providers
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
profile(profile) {
return {
id: profile.sub,
name: profile.name,
googleEmailVerified: profile.email_verified,
email: profile.email,
image: profile.picture,
firstLogin: new Date(),
role: 'USER',
locale: profile.locale,
isSubscribed: false,
};
},
}),
],
session: {
strategy: 'database',
maxAge: 7 * 24 * 60 * 60, // 7 days
updateAge: 30 * 60, // 24 hours
},
pages: {
signIn: '/login',
signOut: '/',
error: '/error', // Error code passed in query string as ?error=
verifyRequest: '/auth/verify-request', // (used for check email message)
newUser: '/tools/project',
},
callbacks: {
async session({ session, user }) {
if (session?.user) {
session.user.role = user.role;
session.user.firstLogin = user.firstLogin;
session.user.locale = user.locale;
session.user.isSubscribed = user.isSubscribed;
session.user.googleEmailVerified = user.googleEmailVerified;
session.user.id = user.id;
}
return session;
},
async redirect({ url, baseUrl }) {
return url.startsWith(baseUrl)
? Promise.resolve(url)
: Promise.resolve(baseUrl);
},
},
debug : process.env.NODE_ENV === "development",
adapter: MongoDBAdapter(clientPromise),
});
If a user logs in it generates three tables in my Mongodb instance:
User, Account and Session