自定义会话next js next-auth

gijlo24d  于 2023-03-12  发布在  其他
关注(0)|答案(3)|浏览(229)

我在迁移我的js文件jo tsx时遇到了一个问题,我正在使用凭据登录,并根据我的用户数据自定义会话用户

// api/auth/[...nextauth].js

import NextAuth from "next-auth";
import Providers from "next-auth/providers";
import { ConnectDatabase } from "../../../lib/db";
import { VertifyPassword } from "../../../lib/password";
import { getSelectedUser } from "../../../helpers/database";
import { MongoClient } from "mongodb";
import { NextApiRequest } from "next";

interface credentialsData {
 data: string | number;
 password: string;
}
export default NextAuth({
 session: {
   jwt: true,
 },
 callbacks: {
   async session(session) {
     const data = await getSelectedUser(session.user.email);
     session.user = data.userData;

// inside data.userdata is a object
// {
//   _id: '60a92f328dc04f58207388d1',
//   email: 'user@user.com',
//   phone: '087864810221',
//   point: 0,
//   role: 'user',
//   accountstatus: 'false'
// }
     return Promise.resolve(session);
   },
 },
 providers: [
   Providers.Credentials({
     async authorize(credentials: credentialsData, req: NextApiRequest) {
       let client;
       try {
         client = await ConnectDatabase();
       } catch (error) {
         throw new Error("Failed connet to database.");
       }

       const checkEmail = await client
         .db()
         .collection("users")
         .findOne({ email: credentials.data });
       const checkPhone = await client
         .db()
         .collection("users")
         .findOne({ phone: credentials.data });

       let validData = {
         password: "",
         email: "",
       };

       if (!checkEmail && !checkPhone) {
         client.close();
         throw new Error("Email atau No HP tidak terdaftar.");
       } else if (checkEmail) {
         validData = checkEmail;
       } else if (checkPhone) {
         validData = checkPhone;
       }

       const checkPassword = await VertifyPassword(
         credentials.password,
         validData.password
       );
       if (!checkPassword) {
         client.close();
         throw new Error("Password Salah.");
       }
       client.close();

// inside validData is a object
// {
//   _id: '60a92f328dc04f58207388d1',
//   email: 'user@user.com',
//   phone: '087864810221',
//   point: 0,
//   role: 'user',
//   accountstatus: 'false'
// }

       return validData;
     },
   }),
 ],
});
// as default provider just return session.user just return email,name, and image, but I want custom the session.user to user data what I got from dababase

这在客户端

// index.tsx

export const getServerSideProps: GetServerSideProps<{
  session: Session | null;
}> = async (context) => {
  const session = await getSession({ req: context.req });

  if (session) {
    if (session.user?.role === "admin") {
      return {
        redirect: {
          destination: "/admin/home",
          permanent: false,
        },
      };
    }
  }
  return {
    props: {
      session,
    },
  };
};

但在客户方面我得到了警告

Property 'role' does not exist on type '{ name?: string; email?: string; image?: string;

实际上我的文件仍然工作正常,但当我的文件在js,它不是这样的警告
有人能帮我修一下吗?

neekobn8

neekobn81#

不确定你是否找到了一个解决方法,但是你还需要配置jwt回调!下面是我的一个项目中的一个例子:

callbacks: {
        async session(session, token) {
            session.accessToken = token.accessToken;
            session.user = token.user;
            return session;
        },
        async jwt(token, user, account, profile, isNewUser) {
            if (user) {
                token.accessToken = user._id;
                token.user = user;
            }
            return token;
        },
    },

解释一下。jwt函数总是在session之前运行,所以你传递给jwt令牌的任何数据都会在session函数上可用,你可以用它做任何你想做的事情。在jwt函数中,我检查是否有用户,因为只有当你登录时才返回数据。

pxy2qtax

pxy2qtax2#

我想现在你已经解决了这个问题,但是因为我在这个页面遇到了同样的问题,我想我应该把我的解决方案发布出来。以防别人遇到它。我是typescript/nextjs的新手,没有意识到我只需要创建一个类型定义文件就可以把角色字段添加到会话中。user
我创建了/types/next-auth.d.ts

import NextAuth from "next-auth";

declare module "next-auth" {
  interface Session {
    user: {
      id: string;
      username: string;
      email: string;
      role: string;
      [key: string]: string;
    };
  }
}

然后我不得不将其添加到我的tsconfig.json中

"include": ["next-env.d.ts", "types/**/*.ts", "**/*.ts", "**/*.tsx"],
daolsyd0

daolsyd03#

我喜欢@klc3rd的答案,但是你可以更精确地使用类型扩展,而不是覆盖DefaultSession中定义的属性:

import { type DefaultSession } from 'next-auth';

declare module 'next-auth' {
  /**
   * Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
   */
  interface Session {
    user?: {
      id: string;
      role?: string;
      username?: string;
      someExoticUserProperty?: string;
    } & DefaultSession['user'];
  }
}

另外,请注意user被 * 标记为可选 *,这是因为useSession默认情况下在客户端上工作并获取用户的会话,并且在获取完成之前,user属性可以为undefined

相关问题