最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - NextAuth.js CallbackRouteError: fetch failed when using Credentials Provider - Stack Overflow

programmeradmin4浏览0评论

I'm trying to implement authentication using NextAuth.js with the Credentials Provider. However, when I try to sign in, I get the following error:

[auth][error] CallbackRouteError: Read more at #callbackrouteerror
[auth][cause]: TypeError: fetch failed

Here is my app/lib/auth.js file:

import NextAuth from "next-auth";
import Credentials from "next-auth/providers/credentials";

const URL = process.env.NEXT_PUBLIC_API_URL;
const Token = process.env.NEXT_PUBLIC_TOKEN;

export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    Credentials({
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
      },
      authorize: async (credentials) => {
        const { email, password } = credentials;
        console.log(email, password);
        console.log(`${URL}auth/jwt/create/`);
        const body = JSON.stringify({ email, password });
        const res = await fetch(`${URL}auth/jwt/create/`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body,
        });

        if (!res.ok) {
          throw new Error("Failed to sign in");
        } else {
          const data = await res.json();
          return data;
        }
      },
    }),
  ],
});

My login component:

import { signIn } from "@/app/lib/auth";
import { executeAction } from "../lib/executeAction";

function Page() {
  return (
    <main>
      <form
        action={async (formData) => {
          "use server";
          await executeAction({
            actionFn: async () => {
              await signIn("credentials", formData);
            },
          });
        }}
      >
        <h1>Sign in</h1>
        <input name="email" type="email" required />
        <input name="password" type="password" required />
        <button type="submit">Sign in</button>
      </form>
    </main>
  );
}

export default Page;

My API route at app/api/auth/[...nextauth]/route.js:

import { handlers } from "@/app/lib/auth";
export const { GET, POST } = handlers;

What I've checked so far:

  • NEXT_PUBLIC_API_URL and NEXT_PUBLIC_TOKEN are correctly set in my .env.local file.
  • The backend URL and the endpoint (auth/jwt/create/) are correct.
  • The backend is running and reachable via Postman/cURL.

Despite this, fetch fails inside authorize. What could be causing this, and how can I fix it?

I'm trying to implement authentication using NextAuth.js with the Credentials Provider. However, when I try to sign in, I get the following error:

[auth][error] CallbackRouteError: Read more at https://errors.authjs.dev#callbackrouteerror
[auth][cause]: TypeError: fetch failed

Here is my app/lib/auth.js file:

import NextAuth from "next-auth";
import Credentials from "next-auth/providers/credentials";

const URL = process.env.NEXT_PUBLIC_API_URL;
const Token = process.env.NEXT_PUBLIC_TOKEN;

export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    Credentials({
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
      },
      authorize: async (credentials) => {
        const { email, password } = credentials;
        console.log(email, password);
        console.log(`${URL}auth/jwt/create/`);
        const body = JSON.stringify({ email, password });
        const res = await fetch(`${URL}auth/jwt/create/`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body,
        });

        if (!res.ok) {
          throw new Error("Failed to sign in");
        } else {
          const data = await res.json();
          return data;
        }
      },
    }),
  ],
});

My login component:

import { signIn } from "@/app/lib/auth";
import { executeAction } from "../lib/executeAction";

function Page() {
  return (
    <main>
      <form
        action={async (formData) => {
          "use server";
          await executeAction({
            actionFn: async () => {
              await signIn("credentials", formData);
            },
          });
        }}
      >
        <h1>Sign in</h1>
        <input name="email" type="email" required />
        <input name="password" type="password" required />
        <button type="submit">Sign in</button>
      </form>
    </main>
  );
}

export default Page;

My API route at app/api/auth/[...nextauth]/route.js:

import { handlers } from "@/app/lib/auth";
export const { GET, POST } = handlers;

What I've checked so far:

  • NEXT_PUBLIC_API_URL and NEXT_PUBLIC_TOKEN are correctly set in my .env.local file.
  • The backend URL and the endpoint (auth/jwt/create/) are correct.
  • The backend is running and reachable via Postman/cURL.

Despite this, fetch fails inside authorize. What could be causing this, and how can I fix it?

Share Improve this question asked Apr 1 at 1:05 LucasLucas 1,5002 gold badges21 silver badges43 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

it seems that your not usign the correct format for the credentials. Here is an example of the correct format based on the documentation. https://next-auth.js./providers/credentials

I think with the correct format it should be something like this

// Modified app/lib/auth.js
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";

// Make sure we actually have these variables
const URL = process.env.NEXT_PUBLIC_API_URL || "";
const Token = process.env.NEXT_PUBLIC_TOKEN || "";

export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        try {
          if (!URL) {
            console.error("API URL is not defined");
            return null;
          }
          
          const { email, password } = credentials;
          console.log(`Attempting to authenticate: ${email}`);
          console.log(`Endpoint: ${URL}auth/jwt/create/`);
          
          // Full URL with protocol
          const fullUrl = URL.startsWith('http') ? `${URL}auth/jwt/create/` : `https://${URL}auth/jwt/create/`;
          
          const response = await fetch(fullUrl, {
            method: "POST",
            headers: {
              "Content-Type": "application/json",
              // Add the token if needed for authentication
              ...(Token && { "Authorization": `Bearer ${Token}` })
            },
            body: JSON.stringify({ email, password }),
          });

          if (!response.ok) {
            console.error(`Auth failed with status: ${response.status}`);
            return null;
          }

          const data = await response.json();
          
          // Return user object that NextAuth expects
          return {
            id: email,
            email,
            // Include tokens from your API if needed
            accessToken: data.access,
            refreshToken: data.refresh
          };
        } catch (error) {
          console.error("Authorization error:", error);
          return null;
        }
      },
    }),
  ],
  callbacks: {
    async jwt({ token, user }) {
      // Initial sign in
      if (user) {
        return {
          ...token,
          accessToken: user.accessToken,
          refreshToken: user.refreshToken
        };
      }
      return token;
    },
    async session({ session, token }) {
      session.user.accessToken = token.accessToken;
      session.user.refreshToken = token.refreshToken;
      return session;
    }
  },
  pages: {
    signIn: '/login',
  }
});

发布评论

评论列表(0)

  1. 暂无评论