Next-Auth 凭据不返回会话,也不通过 prisma 适配器将会话和帐户存储在数据库中

Mar*_*icz 6 authentication axios next.js next-auth

我正在尝试使用 next-auth、github 和 google 实现凭证部分,就像 charm 一样,通过这些提供商登录后,我通过 prisma 适配器将用户、帐户、会话正确存储在 db psql 中,而使用凭证时,我从 api 获取 200当用户和传递正确时,但会话仅出现在网络开发选项卡中,但在使用 getSession 时为空。当用户注册时,他正确地获取了 userId ,就像使用 github 和 google 时一样,但是帐户和会话选项卡未填充,我是否应该手动制作它,例如刷新令牌,accessToken 过期并手动添加特定 userId 的数据并将其存储在数据库中的帐户和会话表?

Mik*_*ike 11

CredentialsProvider 与数据库会话不兼容。为了使凭据正常工作,您需要将 Next-Auth 配置为使用 JWT 会话而不是数据库会话。

这可以通过在 Next-Auth 中设置“会话”选项来完成

export default NextAuth({
   session: {
      strategy: "jwt",
      maxAge: 3000,
   }
   providers: []
   ...
})
Run Code Online (Sandbox Code Playgroud)


nne*_*eko 6

正如@Mike所指出的,凭证提供程序仅限于下一个身份验证开发人员仅使用 JWT。但是,您可以通过执行以下操作来实现一种解决方法,使其利用数据库会话:

  1. 创建注册 api 路由,确保使用凭据的所有用户帐户都链接到帐户表中的条目

  2. 使用高级初始化来初始化 NextAuth

  3. 将登录回调注册为 NextAuth 回调选项的一部分,该选项使用提供给 NextAuth 的数据库适配器来使用 createSession 方法创建会话。

     async signIn({ user, account, profile, email, credentials }) {
         // Check if this sign in callback is being called in the credentials authentication flow. If so, use the next-auth adapter to create a session entry in the database (SignIn is called after authorize so we can safely assume the user is valid and already authenticated).
         if (req.query.nextauth.includes('callback') && req.query.nextauth.includes('credentials') && req.method === 'POST') {
             if (user) {
                 const sessionToken // Implement a function to generate the session token (you can use randomUUID as an example)
                 const sessionExpiry // Implement a function to calculate the session cookie expiry date
    
                 await adapter.createSession({
                     sessionToken: sessionToken,
                     userId: user.id,
                     expires: sessionExpiry
                 })
    
                 const cookies = new Cookies(req,res)
    
                 cookies.set('next-auth.session-token', sessionToken, {
                     expires: sessionExpiry
                 })
             }   
         }
    
         return true;
     }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 在 NextAuth选项中为和jwt提供新功能。这些函数应该检查身份验证流是否在以及提供者是否在中。使用凭据提供程序时,应以字符串形式返回编码中的 sessionToken,并始终返回 null 进行解码。在凭证之外应该执行正常的 JWT 编码和解码行为。encodedecodecallbackcredentials

    jwt: {
         // Customize the JWT encode and decode functions to overwrite the default behaviour of storing the JWT token in the session cookie when using credentials providers. Instead we will store the session token reference to the session in the database.
         encode: async (token, secret, maxAge) => {
             if (req.query.nextauth.includes('callback') && req.query.nextauth.includes('credentials') && req.method === 'POST') {
                 const cookies = new Cookies(req,res)
    
                 const cookie = cookies.get('next-auth.session-token')
    
                 if(cookie) return cookie; else return '';
    
             }
             // Revert to default behaviour when not in the credentials provider callback flow
             return encode(token, secret, maxAge)
         },
         decode: async (token, secret) => {
             if (req.query.nextauth.includes('callback') && req.query.nextauth.includes('credentials') && req.method === 'POST') {
                 return null
             }
    
             // Revert to default behaviour when not in the credentials provider callback flow
             return decode(token, secret)
         }
     },
    
    Run Code Online (Sandbox Code Playgroud)

上面的两个函数必须在 [...nextauth].js api 路由的 auth(req, res) 处理程序中定义,因为它们需要位于相同的范围内才能访问原始 http 请求以及由下一步授权。

示例代码可以在 GitHub 问题#4394的响应下找到,或者要了解更详细的解释,请阅读我创建的这篇博客文章。