如何在 next-auth 中向客户端 API 添加数据?

How do I add data to the client API in next-auth?

我目前正在使用凭据提供程序使用 next-auth 进行授权,我有会话工作并且用户可以登录等。但是,在会话中我需要使用客户端传递一些数据 API、用户、名字、姓氏、用户名和电子邮件。

默认情况下,客户端 API 传递姓名、电子邮件和图像,但是,我如何更改它以添加上述数据,这是我目前所拥有的。

index.js

import { useState, useEffect  } from 'react';
import { getSession } from 'next-auth/client'
import { useRouter } from 'next/router';
import Link from 'next/link';
import Head from 'next/head';
import Sidebar from '../components/Sidebar';

export default function Dashboard({ user}) {
  return (
    <div>
      <Head>
        <title>Dashboard</title>
      </Head>

      <Sidebar />

      <section className="content dashboard-content">
        <h1>Dashboard</h1>

        <h3>Welcome to Ellis development {user.firstname }</h3>
      </section>
    </div>
  )
}

export async function getServerSideProps(ctx) {
  const session = await getSession(ctx);
  
  if (!session) {
    return {
      redirect: {
        destination: '/dashboard/auth/login',
        permanent: false
      },
    }
  }

  console.log(session);

  return {
    props: {
      user: {
        firstname: session.user.firstname,
        lastname: session.user.lastname,
        username: session.user.username,
        email: session.user.email,
      }
    },
  }
}

[...nextauth.js]

import NextAuth from 'next-auth';
import Providers from 'next-auth/providers';

import { verifyPassword } from '../../../lib/auth';
import { connectToDatabase } from '../../../lib/mongodb';

export default NextAuth({
  session: {
    jwt: true,
  },
  providers: [
    Providers.Credentials({
      async authorize(credentials) {
        const client = await connectToDatabase();
        const usersCollection = client.db().collection('users');

        const user = await usersCollection.findOne({
          email: credentials.email,
        });

        if (!user) {
          client.close();
          throw new Error('No user found!');
        }

        const isValid = await verifyPassword(
          credentials.password,
          user.password
        );

        if (!isValid) {
          client.close();
          throw new Error('Could not log you in!');
        }

        client.close();

        return {
          firstname: user.firstname,
          lastname: user.lastname,
          username: user.username,
          email: user.email
        };
      },
    }),
  ],
});

任何帮助都将非常有用,谢谢。

编辑

我已将以下内容添加到 [...next-auth] 页面

callbacks: {
  session: async (session) => {
    if (!session) return;

    const client = await connectToDatabase();
    const usersCollection = client.db().collection('users');
    
    const userData = await usersCollection.findOne({
      email: session.user.email,
    });

    return {
      session: {
        user: {
          id: userData._id,
          firstname: userData.firstname,
          lastname: userData.lastname,
          username: userData.username,
          email: userData.email
        }
      }
    };
  },
},

这给了我以下结果

{
  session: {
    user: {
      id: '61a107f29ca24c12146d1b22',
      firstname: 'Ben',
      lastname: 'Bagley',
      username: 'benbagley',
      email: 'benbagley@pm.me'
    }
  }
}

所以我现在有了我需要的值,但是,如何将数据呈现到页面上我现在有以下内容

import { getSession } from 'next-auth/client'
import Head from 'next/head';
import Sidebar from '../components/Sidebar';

export default function Dashboard({ session }) {
  return (
    <div>
      <Head>
        <title>Dashboard</title>
      </Head>

      <Sidebar />

      <section className="content dashboard-content">
        <h1>Dashboard</h1>

        <h3>Welcome {session.user.firstname} to Ellis development</h3>
      </section>
    </div>
  )
}

export async function getServerSideProps(ctx) {
  const session = await getSession(ctx);
  
  if (!session) {
    return {
      redirect: {
        destination: '/dashboard/auth/login',
        permanent: false
      },
    }
  }

  console.log(session);

  return {
    props: {
      session: {
        user: {
          id: session.user.id,
          firstname: session.user.firstname,
          lastname: session.user.lastname,
          username: session.user.username,
        }
      }
    },
  }
}

但是,我得到 TypeError: Cannot read properties of undefined (reading 'id')

您应该检查下一个身份验证回调。用户对象将包含电子邮件、图像和名称。您可以使用它来获取内部 api 左右,并将信息附加到将在 jwt 中编码的会话对象。

callbacks: {
        session: async (session, user) => {
            if (!session) return;
            const userServerData = fetch(...); // or some internal logic
            
            session.user.firstName = userServerData.firstName;
            session.user.lastname = userServerData.lastname;
            session.user.username = userServerData.username;
            
            return Promise.resolve(session);
        },
    },

这就是我在项目中解决同样问题的方法

第 1 步:将以下内容添加到 ...[nextauth].ts

  pages: {
    // signIn: '/auth/signin',
    // signOut: '/auth/signout',
    // error: '/auth/error', // Error code passed in query string as ?error=
    // verifyRequest: '/auth/verify-request', // (used for check email message)
    newUser: '/auth/newuser' // New users will be directed here on first sign in 
  },

第 2 步:现在您可以将用户数据和 post 更新到您的 api

'/auth/newuser.ts'

    React.useEffect(() => {
   

       post updated user data to -> "/api/auth/newuserwelcome"

      }, [])

//
Step 3: create api endpoint to save updated user data to DB
    /api/auth/newuserwelcome.ts
      

这里的问题有两个,

a) 没有使用适当的回调来添加和覆盖 next-auth api,例如:

callbacks: {
  session: async (session) => {
    if (!session) return;

    const client = await connectToDatabase();
    const usersCollection = client.db().collection('users');
    
    const userData = await usersCollection.findOne({
      email: session.user.email,
    });

    return {
      session: {
        user: {
          id: userData._id,
          firstname: userData.firstname,
          lastname: userData.lastname,
          username: userData.username,
          email: userData.email
        }
      }
    };
  },
},

传值到此,下一期支撑...

b) 传递 props 时不使用扩展运算符

export async function getServerSideProps(ctx) {
  const session = await getSession(ctx);
  
  if (!session) {
    return {
      redirect: {
        destination: '/dashboard/auth/login',
        permanent: false
      },
    }
  }

  return {
    props: {
      ...session,
    }
  }
}

调用 ...session 获取所有 return 对象并允许它像这样传递 session.user.firstname,非常方便。