NextJs 身份验证与针对 DRF 的 Next-Auth

Posted

技术标签:

【中文标题】NextJs 身份验证与针对 DRF 的 Next-Auth【英文标题】:NextJs Authentication with Next-Auth against DRF 【发布时间】:2021-02-03 22:11:23 【问题描述】:

我有一个退出的 Django 项目,我正试图从模板转移到 NextJs 前端。我遇到了 Next-Auth-js,它在 Next Auth 中似乎很好。

但是,该文档似乎更关注与 JS 相关的后端身份验证。在此example 之后,我已将 NEXTAUTH_URL 环境变量发送到我的 DRF 端点 localhost:8002。虽然前端在 localhost:3000 上运行。虽然我的 _app.js 看起来像这样:

<Provider options=site: process.env.NEXTAUTH_URL, session=pageProps.session  >
  <Component ...pageProps />
</Provider>

使用Nav.js 进行测试,我将登录/输出 href 更改为指向我的 Django 端点,但似乎 next-auth-js 忽略了这一点,并将会话提取放置到我的前端 http://localhost:3000/api/auth/session 而不是http://localhost:8002/api/auth/session.

对于如何使用 Django Rest Framework (DRF) 正确/安全地实施此身份验证的任何帮助,我将不胜感激

【问题讨论】:

NEXTAUTH_URL 的值是多少? NEXTAUTH_URL=localhost:8002/api/account/auth/login in .env 【参考方案1】:

您可以在此处使用callbacks。 https://next-auth.js.org/configuration/callbacks

callbacks: 
  async signIn(user, account, profile) 
    return true
  ,
  async redirect(url, baseUrl) 
    return baseUrl
  ,
  async session(session, user) 
    return session
  ,
  async jwt(token, user, account, profile, isNewUser) 
    return token
  

signIn回调中,可以通过provider登录获取accessToken和tokenId。在这里,调用您的 DRF API 并将这些令牌传递给您的 DRF,当您从 DRF 取回 access_tokenrefresh_token 时。将它们添加到您的用户实例。然后在JWT回调中,从user获取accessrefresh并将它们添加到token

从某个博客得到这个

不过,您还需要处理刷新令牌。

【讨论】:

【参考方案2】:

我认为that is the way it should work,您的 nextjs 站点将是您的 django API client -&gt; nextjs -&gt; DRF 的一种代理/中间件,您应该让它处理会话以及您需要在 API 中为任何身份验证步骤执行的任何操作,将代码放在callbacks 或events 配置中,我认为this tutorial 更适合您的用例

来自docs

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

import Providers from `next-auth/providers`
...
providers: [
  Providers.Credentials(
    // The name to display on the sign in form (e.g. 'Sign in with...')
    name: 'Credentials',
    // The credentials is used to generate a suitable form on the sign in page.
    // You can specify whatever fields you are expecting to be submitted.
    // e.g. domain, username, password, 2FA token, etc.
    credentials: 
      username:  label: "Username", type: "text", placeholder: "jsmith" ,
      password:   label: "Password", type: "password" 
    ,
    authorize: async (credentials) => 
      // Add logic here to look up the user from the credentials supplied
      const user =  id: 1, name: 'J Smith', email: 'jsmith@example.com' 

      if (user) 
        // call your DRF sign in endpoint here
        // Any object returned will be saved in `user` property of the JWT
        return Promise.resolve(user)
       else 
        // If you return null or false then the credentials will be rejected
        return Promise.resolve(null)
        // You can also Reject this callback with an Error or with a URL:
        // return Promise.reject(new Error('error message')) // Redirect to error page
        // return Promise.reject('/path/to/redirect')        // Redirect to a URL
      
    
  )
]

...

  events: 
    signOut: async (message) =>  /* call your DRF sign out endpoint here */ ,
  

【讨论】:

我已经访问过与我的案例无关的教程 b4。我正在使用 Providers.Credentials 和现有的登录/注销端点 (DRF),并创建了应该使用 next-auth signIn() 进行登录的自定义 login.tsx。 @Paullo 我看不出它是如何不相关的,你不应该期望调用 DRF,你应该在 Provider.Credentials 授权方法和 signOut 事件中自己调用这些端点 我已经通过了这些阶段,但是如果您关注此讨论 github.com/nextauthjs/next-auth/issues/280,就会发现这是一个现有问题。不过,这个讨论线程很少有其他人提供帮助。 @Paullo 如果你用你的新进展更新你的问题会很好

以上是关于NextJs 身份验证与针对 DRF 的 Next-Auth的主要内容,如果未能解决你的问题,请参考以下文章

DRF 简单 jwt 从用户实例获取身份验证令牌或更改用户名和密码组合

05 drf源码剖析之认证

NEXT JS 使用 Auth0 运行时错误,一秒钟后消失

“未提供身份验证凭据。”在 DRF 中

在 NextJS 中刷新用户身份验证服务器端?

nextjs 路由中间件进行身份验证