Onu*_*der 20 authentication session csrf reactjs next.js
我一直在尝试为 Next.js 项目实现可靠的身份验证流程,但现在我完全迷失了。我已经看过 Next.js 的示例存储库。但是我对完整的解决方案有很多疑问。
我有一个 express.js API 和一个单独的 Next.js 前端项目。所有数据和身份验证都由 API 处理。前端只是使用 SSR 呈现页面。如果我只是创建一个整体项目,其中呈现页面和所有数据由单个服务器处理(我的意思是 Next.js 的自定义服务器选项),我将只使用 express-session 和 csurf。这将是管理会话和创建针对 CSRF 的安全性的传统方式。
Express.js API 不是必需的。这只是一个例子。它可以是 Django API,也可以是 .Net Core API。重点是,它是一个单独的服务器和一个单独的项目。
我怎样才能拥有一个简单而可靠的结构?我检查了一些我最喜欢的网站(netlify、zeit.co、heroku、spectrum.chat 等)。其中一些使用 localstorage 来存储访问和刷新令牌(易受 XSS 攻击)。其中一些使用 cookie,它们甚至不是 HTTPOnly(XSS 和 CSRF 都容易受到攻击)。像spectrum.chat 这样的例子使用了我上面提到的方式(cookie-session + 防止csrf)。
我知道围绕 JWT 代币有巨大的炒作。但我觉得它们太复杂了。大多数教程只是跳过所有过期、令牌刷新、令牌撤销、黑名单、白名单等。
并且 Next.js 的许多会话 cookie 示例几乎从未提及 CSRF。老实说,身份验证对我来说一直是个大问题。有一天我读到应该使用 HTTPOnly cookie,第二天我看到一个巨大的流行网站甚至没有使用它们。或者他们说“永远不要将你的代币存储到 localStorage”,而一些大型项目就使用这种方法。
任何人都可以向我指出这种情况的方向吗?
Iai*_*ins 11
免责声明:我是下面免费开源包的维护者,但我认为它在这里是合适的,因为这是一个没有很好答案的常见问题,因为许多流行的解决方案都有问题中提出的特定安全漏洞(例如在适当的情况下不使用 CSRF 并将会话令牌或网络令牌暴露给客户端 JavaScript)。
NextAuth.js包试图通过免费的开源软件解决上述问题。
httpOnly
带有secure
.__HOST-
或__Secure
)。例如 page/api/auth/[...nextauth.js]
import NextAuth from 'next-auth'
import Providers from 'next-auth/providers'
const options = {
providers: [
// OAuth authentication providers
Providers.Apple({
clientId: process.env.APPLE_ID,
clientSecret: process.env.APPLE_SECRET
}),
Providers.Google({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET
}),
// Sign in with email (passwordless)
Providers.Email({
server: process.env.MAIL_SERVER,
from: '<no-reply@example.com>'
}),
],
// MySQL, Postgres or MongoDB database (or leave empty)
database: process.env.DATABASE_URL
}
export default (req, res) => NextAuth(req, res, options)
Run Code Online (Sandbox Code Playgroud)
例如 pages/index.js
import React from 'react'
import {
useSession,
signin,
signout
} from 'next-auth/client'
export default () => {
const [ session, loading ] = useSession()
return <p>
{!session && <>
Not signed in <br/>
<button onClick={signin}>Sign in</button>
</>}
{session && <>
Signed in as {session.user.email} <br/>
<button onClick={signout}>Sign out</button>
</>}
</p>
}
Run Code Online (Sandbox Code Playgroud)
即使您不选择使用它,您也可能会发现该代码作为参考很有用(例如,如何处理JSON Web 令牌以及如何在会话中轮换它们。
对于我当前的项目,我也不得不考虑这个问题。我使用相同的技术:ExpressJS API 和 NextJS 服务器端渲染的前端。
我选择做的是在 ExpressJS API 中使用passport.js。YouTube 上的 TheNetNinja 有一个非常好的播放列表,共有 21 集。他向您展示了如何在您的 API 中实现 Google OAuth 2.0,但此逻辑转移到任何其他策略(JWT、电子邮件 + 密码、Facebook 身份验证等)。
在前端,我会将用户重定向到 Express API 中的 url。这个 url 会向用户显示 Google OAuth 屏幕,用户点击“允许”,API 会做更多的事情,为特定用户制作一个 cookie,然后重定向回前端的 url。现在,用户已通过身份验证。
关于HTTPOnly cookie:我选择关闭此功能,因为我在cookie中存储了前端需要的信息。如果您启用了此功能,那么前端 (javascript) 将无法访问这些 cookie,因为它们是 HTTPOnly。
这是我正在谈论的播放列表的链接:https : //www.youtube.com/watch?v=sakQbeRjgwg&list=PL4cUxeGkcC9jdm7QX143aMLAqyM-jTZ2x
希望我给了你一个你可以采取的方向。
编辑:我还没有回答你关于 CSURF 的问题,但那是因为我不熟悉它。
我终于找到解决办法了!
现在我使用 csrf npm 包,而不是 csurf。csurf 只是将 csrf 变成一个快速中间件。
因此,我在 _app 的 getInitialProps 中创建了一个 csrfSecret。它创建秘密,并将其设置为 httpOnly cookie。随后,它创建一个 csrfToken 并通过 pageProps 返回它。所以,我可以通过窗口访问它。NEXT_DATA .props.csrfToken。如果用户刷新页面,csrfSecret 保持不变,但 csrfToken 会更新。
当我向代理的“/api/graphql API 路由发出请求时,它首先从 x-xsrf-token 标头获取 csrf 令牌,并使用 csrfSecret cookie 值对其进行验证。之后,它提取 authToken cookie 的值并传递它到实际的 GraphQL API。
API 全部基于令牌。它只需要一个不过期的访问令牌。(顺便说一句,它不需要是 JWT。可以使用任何加密强度高的随机令牌。这意味着引用/不透明令牌。)
实际的 API 不需要 CSRF 检查,因为它不依赖 cookie 进行身份验证。它仅检查授权标头。authToken 和 csrfSecret 都是 httpOnly cookies。我什至从未将它们存储在客户端内存中。
我认为这是我所能得到的最安全的。现在我对这个解决方案很满意。
归档时间: |
|
查看次数: |
8680 次 |
最近记录: |