如何在Next 13 appDir中实现外部API登录next-auth

roqulrg3  于 2023-04-20  发布在  其他
关注(0)|答案(2)|浏览(166)

嗨,我试图实现一个登录与下一个13有appDir: true和下一个的版本是13.3.0,但我检查了文档,但事实是我不明白,我这样做与 typescript ,但几乎没有文档,我不知道如果我这样做是正确的。
app/API/auth/[...nextauth]/route.ts

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

const handler = NextAuth({
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        username: { label: "Username", type: "text" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials, req) {
        const { username, password } = credentials as { username: string; password: string };
        const res = await fetch("http://localhost:3000/api/auth/login", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ username, password }),
        });
        const user = await res.json();
        if (res.ok) {
          return user;
        } else {
          return null;
        }
      },
    }),
  ],
  session: {
    strategy: "jwt"
  },
});

export { handler as GET, handler as POST };

layout.tsx

'use client'

import './globals.css'
import { SessionProvider } from "next-auth/react"

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body>
        <SessionProvider>
          {children}
        </SessionProvider>
      </body>
    </html>
  )
}

当我添加<SessionProvider>{children}</SessionProvider>时,我得到以下错误,它不加载页面。x1c 0d1x

ix0qys7i

ix0qys7i1#

第一个

看起来仍然是under development
你可以关注这个仓库的最新变化。一旦有一个工作的例子,我会更新这个答案。

可能是您的await fetch(...)调用返回了一个HTTP 500 Internal Server Error代码,并返回了一个错误页面,这是一个无效的JSON文档。
添加console.log(await res.text())而不是const user = await res.json()来验证这一点。

qcbq4gxm

qcbq4gxm2#

app/API/auth/[... nextauth]/route.ts

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

interface User {
  id: number;
  name: string;
  email: string;
  password: string;
  role: string;
  created_at: string;
  updated_at?: any;
  iat: number;
  exp: number;
  jti: string;
}

const handler = NextAuth({
  session: {
    strategy: "jwt",
  },
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "text", placeholder: "jsmith" },
        password: { label: "Password", type: "password" },
      },
      async authorize(credentials) {
        const { email, password } = credentials as {
          email: string;
          password: string;
        };
        const res = await fetch("http://127.0.0.1:8000/login", {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ email, password }),
        });
        // tipar peticion de user
        const user = await res.json();
        if (res.ok && user) {
          // mostrar el encabezado de autorización en la consola
          return user;
        } else {
          return null;
        }
      },
    }),
  ],
  callbacks: {
    jwt: async ({ token, user }) => {
      if (user) token = user as unknown as { [key: string]: any };
      console.log(token);
      
      return token;
    },
    session: async ({ session, token }) => {
      session.user = { ...token }
      return session;
    },
  },
  secret: "supersecret",
  pages: {
    signIn: "/login",
  },
});

export { handler as GET, handler as POST };

app/Providers.tsx

'use client'

import React, { ReactNode } from 'react';
import { SessionProvider } from "next-auth/react"

interface Props {
    children: ReactNode
}

function Providers({ children }: Props) {
  return <SessionProvider>{children}</SessionProvider>
}

export default Providers;

layout.tsx

import { ReactNode } from 'react'
import './globals.css'
import Provider from './Providers'

interface Props {
  children: ReactNode
}

export default function RootLayout({ children }: Props) {
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <meta name="description" content="Generated by create next app" />
        <meta name="author" content="Vercel" />
        <link rel="stylesheet" href="https://cdn.lineicons.com/4.0/lineicons.css" />
      </head>
      <body>
        <Provider>{children}</Provider>
      </body>
    </html>
  )
}

并且当发送凭证时,发送相同的凭证和数据。

相关问题