Search code examples
next.jsmiddlewarevercelnext-auth

My Next.js middleware works only in localhost, how to make it works in Vercel deploy too?


I am learning Next.js and I just made a simple middleware.ts:

export { default } from 'next-auth/middleware';
export const config = { matcher: ['/items', '/dashboard'] };

The problem is: the middleware works well, if I have not a session, I can't acess /items and /dashboard, but this only works in development (in my localhost). When I deploy in Vercel, this happen:

  1. If I am not in a session, it works and ask me to do a login(that's what I expect and works well)
  2. But if I do have a session and try to acess /items or /dashboard, it just redirect me to "/", the main home directory(that doesn't need session to acess) a That's my [...nextauth]/**route.ts** just in case:
import NextAuth from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import { compare } from 'bcrypt';
import { sql } from '@vercel/postgres';

const handler = NextAuth({
  session: {
    strategy: 'jwt',
  },
  pages: {
    signIn: '/login',
  },
  providers: [
    CredentialsProvider({
      credentials: {
        email: {},
        password: {},
      },
      async authorize(credentials, req) {
        //
        const response = await sql`
        SELECT * FROM users WHERE email=${credentials?.email}`;
        const user = response.rows[0];

        const passwordCorrect = await compare(
          credentials?.password || '',
          user.password
        );

        console.log({ passwordCorrect });

        if (passwordCorrect) {
          return {
            id: user.id,
            email: user.email,
          };
        }

        return null;
      },
    }),
  ],
});

export { handler as GET, handler as POST };

And that's the folder structure of the mentioned files:

├── app
 ├── api
  └── auth
   └── [...nextauth]
    └── **route.ts**
 ├── items
  └── page.tsx
 ├── dashboard
  └── page.tsx
├── public
├── .env
├── **middleware.ts**
├── next.config.mjs
├── README.md

So in resume, the middleware works perfeclty in localhost but in Vercel deploy it just redirect me to "/" (only if I do have a session, if I don't have one, it shows de login page as expected)

edit: I just tried to open my app in web again but this time I get the error that shows in console log from browser:

error that shows in console log

and thats my Login page app/login/form.tsx:

"use client";

import { signIn } from "next-auth/react";
import { useRouter } from "next/navigation";
import { FormEvent } from "react";

export default function Form() {
  const router = useRouter();
  const handleSubmit = async (e: FormEvent<HTMLFormElement>) => {
    e.preventDefault();
    const formData = new FormData(e.currentTarget);
    const response = await signIn("credentials", {
      email: formData.get("email"),
      password: formData.get("password"),
      redirect: false,
    });
    console.log({ response });
    if (!response?.error) {
      router.push("/items");
      router.refresh();
    }
  };
  return (
    <form onSubmit={handleSubmit}>
      {/* E-mail */}
      <div className="mb-4">
        <label
          htmlFor="email"
          className="block text-gray-700 text-sm font-bold mb-2"
        >
          E-mail
        </label>
        <input
          type="email"
          id="email"
          name="email"
          className="w-full p-2 border border-gray-300 rounded"
          placeholder="Seu e-mail"
          required
        />
      </div>

      {/* Senha */}
      <div className="mb-6">
        <label
          htmlFor="password"
          className="block text-gray-700 text-sm font-bold mb-2"
        >
          Senha
        </label>
        <input
          type="password"
          id="password"
          name="password"
          className="w-full p-2 border border-gray-300 rounded"
          placeholder="Sua senha"
          required
        />
      </div>

      {/* Botão de Entrar */}
      <button
        type="submit"
        className="w-full bg-blue-500 text-white p-2 rounded hover:bg-blue-600 transition duration-300"
      >
        Login
      </button>
    </form>
  );
}

And thats de app/login/page.tsx:

import { getServerSession } from "next-auth";
import Form from "./form";
import { redirect } from "next/navigation";

export default async function LoginPage() {
  const session = await getServerSession();
  if (session) {
    redirect("/");
  }
  return (
    <main className="flex flex-col items-center justify-center bg-gray-100 h-full w-full">
      <div className="flex items-center justify-center ">
        <div className="bg-white p-8 rounded shadow-md w-96">
          <h1 className="text-2xl font-bold mb-4">Login</h1>

          {/* Formulário */}
          <Form />
        </div>
      </div>
    </main>
  );
}


Solution

  • Solution: I discovered the solution, it has nothing to do with the code, but with Vercel Environment Variables, i discovered this by deploying my projet on Railway and it works perfectly, then I just deleted every Environment Variables on Vercel I could and set up new variables, made a new deploy to take effect on the new variables and the problem is gone.