Next-Auth凭据没有返回会话并且未通过Prisma适配器将会话和帐户存储在数据库中。

6

我正在尝试使用Next-Auth实现凭据部分,github和google工作得很好,在通过这些提供程序登录后,用户、账户和会话都能正确地通过prisma适配器存储到psql数据库中。但是当使用凭据时,如果用户名和密码正确我会收到来自api的200响应,但是会话仅在网络开发选项卡中出现,但在使用getSession时为null。 当用户注册时,他可以正确地获取类似于使用github和google时的userId,但是账户和会话选项卡没有被填充,我应该手动填写它们吗?比如手动添加特定userId的refreshToken、accessToken到Account和Session表中并将其存储在数据库中?

2个回答

10

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

可以通过在 Next-Auth 中设置 "session" 选项来完成此操作。

export default NextAuth({
   session: {
      strategy: "jwt",
      maxAge: 3000,
   }
   providers: []
   ...
})

1
在看到你的答案之前,我尝试了很多次,谢谢兄弟! - Tugrul Yildirim
1
一样的,你是我的救星伙计! - korvus

5

正如@Mike指出的那样,下一个认证开发人员只允许凭据提供程序使用JWT。然而,您可以通过执行以下操作来实现解决方法,以利用数据库会话:

  1. Create a signup api route that ensures that all user accounts that use credentials are linked to an entry in the accounts table

  2. Initialize NextAuth using advanced initialization

  3. Register a signIn callback as a part of the NextAuth callback options that uses the database adapter provided to NextAuth to create a session using the createSession method.

     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;
     }
    
  4. In the NextAuth jwt options provide new functions for the encode and decode. These functions should check that the auth flow is in the callback and also that the provider is credentials. When using the credentials provider is should return as a String the sessionToken in the encode and always return null for decode. Outside the credentials is should do the normal JWT encode and decode behaviours.

    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)
         }
     },
    

以上两个函数必须在auth(req, res)处理程序内定义,以便[...nextauth].js API路由中它们需要处于同一作用域,才能访问原始HTTP请求以及NextAuth提供的选项。

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接