Search code examples
typescriptsessionnext.jsprismanext-auth

nextjs 13 middleware not working properly


I have a couple of pages that needs the user to be logged in. So I have used middleware for checking that out and blacklisting those pages by forcing the user to login to see/use them. This is the code I have in the file:

export {default} from "next-auth/middleware";

export const config = {
    matcher: ["/api/:path*", "/new"]
}

Even though, a user is logged in, and visits the /new route, he is asked again to signing, while the expected behavior is to let the authenticated users use the route. The issue if with the /api/*

I am using Prisma as the adapter. Here is my next-auth config file:

// /api/auth/[...nextauth]/options.ts
import { prisma } from "@/lib/database";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { type NextAuthOptions } from "next-auth";
import GithubProvider from "next-auth/providers/github";
import GoogleProvider from "next-auth/providers/google";

export const authOptions: NextAuthOptions = {
  adapter: PrismaAdapter(prisma),
  secret: process.env.NEXTAUTH_SECRET,
  session: {
    maxAge: 30 * 60,
  },
  debug: process.env.NODE_ENV === "development" ? true : false,
  pages: {
    signIn: "/auth/login",
  },
  providers: [
    GithubProvider({
      clientId: process.env.GITHUB_CLIENT_ID as string,
      clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
    }),
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID as string,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
    }),
  ],
};

I import this config into /api/auth/[...nextauth]/route.ts which is as follows:

import NextAuth from "next-auth/next";
import { authOptions } from "./options";

const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };

And here is my schema.prisma file:

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider     = "mysql"
  url          = env("DATABASE_URL")
  relationMode = "prisma"
}

model Todo {
  id               String   @id @default(cuid())
  todo_name        String
  todo_description String?
  completed        Boolean? @default(false)
  createdAt        DateTime @default(now())
  updatedAt        DateTime @updatedAt
  user             User?    @relation(fields: [userId], references: [id])
  userId           String?

  @@index([userId])
}

model Account {
  id                String  @id @default(cuid())
  userId            String
  type              String
  provider          String
  providerAccountId String
  refresh_token     String? @db.Text
  access_token      String? @db.Text
  expires_at        Int?
  token_type        String?
  scope             String?
  id_token          String? @db.Text
  session_state     String?

  user User @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
  @@index([userId])
}

model Session {
  id           String   @id @default(cuid())
  sessionToken String   @unique
  userId       String
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@index([userId])
}

model User {
  id            String    @id @default(cuid())
  name          String?
  email         String?   @unique
  emailVerified DateTime?
  image         String?
  accounts      Account[]
  sessions      Session[]
  todos         Todo[]
}

model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
}

Any help over this is much appreciated


Solution

  • Found a solution that works https://stackoverflow.com/a/75732207/13770585

    setting the session strategy to jwt does the workaround

    Need to add this part into your authOptions

    export const authOptions: NextAuthOptions = {
      adapter: PrismaAdapter(prisma),
      secret: process.env.NEXTAUTH_SECRET,
      session: {
        maxAge: 30 * 60,
        strategy: "jwt", // <- this does the job
      },
      debug: process.env.NODE_ENV === "development" ? true : false,
      pages: {
        signIn: "/auth/login",
      },
      providers: [
        GithubProvider({
          clientId: process.env.GITHUB_CLIENT_ID as string,
          clientSecret: process.env.GITHUB_CLIENT_SECRET as string,
        }),
        GoogleProvider({
          clientId: process.env.GOOGLE_CLIENT_ID as string,
          clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
        }),
      ],
    };