Currently, I am developing a Next.js 14.0.3 application that utilizes next-auth for authentication. The application interacts with an external NestJS backend for authorization and JWT validation. While everything functions correctly in the development environment (using npm run dev), I encounter an error during the production build process (using npm run build).
.next/types/app/api/auth/[...nextauth]/route.ts:8:13
Type error: The type 'OmitWithTag<typeof import("U:/sid/sid-front/app/api/auth/[...nextauth]/route"), "POST" | "GET" | "HEAD" | "OPTIONS" | "PUT" | "DELETE" | "PATCH" | "config" | "generateStaticParams" | "revalidate" | ... 5 more ... | "maxDuration", "">' does not meet the requirements of the constraint '{ [x: string]: never; }'.
The property 'authOptions' is incompatible with the index signature.
The type 'AuthOptions' cannot be assigned to 'never'.
The content of my [...nextauth]/route.ts file is as follows:
import { NextAuthOptions } from "next-auth";
import { JWT } from "next-auth/jwt";
import NextAuth from "next-auth/next";
import CredentialsProvider from "next-auth/providers/credentials";
async function refreshToken(token: JWT): Promise<JWT> {
const res = await fetch(process.env.NEXT_PUBLIC_API_URL + "/auth/refresh", {
method: "POST",
headers: {
authorization: `Refresh ${token.backendTokens.refreshToken}`,
},
});
console.log("refreshed");
const response = await res.json();
return {
...token,
backendTokens: response,
};
}
export const authOptions: NextAuthOptions = {
providers: [
CredentialsProvider({
name: "Credentials",
credentials: {
email: {
label: "Email",
type: "text",
placeholder: "jsmith",
},
password: { label: "Password", type: "password" },
},
async authorize(credentials, req) {
if (!credentials?.email || !credentials?.password) return null;
const { email, password } = credentials;
const res = await fetch(
process.env.NEXT_PUBLIC_API_URL + "/auth/login",
{
method: "POST",
body: JSON.stringify({
email,
password,
}),
headers: {
"Content-Type": "application/json",
},
}
);
if (res.status == 401) {
console.log(res.statusText);
return null;
}
const user = await res.json();
return user;
},
}),
],
callbacks: {
async jwt({ token, user }) {
if (user) return { ...token, ...user };
if (new Date().getTime() < token.backendTokens.expiresIn) return token;
return await refreshToken(token);
},
async session({ token, session }) {
session.user = token.user;
session.backendTokens = token.backendTokens;
return session;
},
},
};
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
In addition to the above code, here is my next-auth.d.ts file:
import NextAuth from "next-auth";
declare module "next-auth" {
interface Session {
user: {
id: number;
email: string;
name: string;
};
backendTokens: {
accessToken: string;
refreshToken: string;
expiresIn: number;
};
}
}
import { JWT } from "next-auth/jwt";
declare module "next-auth/jwt" {
interface JWT {
user: {
id: number;
email: string;
name: string;
};
backendTokens: {
accessToken: string;
refreshToken: string;
expiresIn: number;
};
}
}