首页 > 其他分享 >NextJs 中使用Next-Auth

NextJs 中使用Next-Auth

时间:2023-07-21 16:36:33浏览次数:41  
标签:这个 const 里面 Auth Next session cookie csrfToken NextJs

NextJs 中使用Next-Auth

本篇讨论的范畴是Azureb2c 做为provider, token的类型是jwt token.我们讨论在Azureb2c 认证完后,由Next-Auth 负责认证的过程。

Basic Concept

  • Token
    这个就是cookie,它的名字是非https是next-auth.session-token,如果是https则是__Secure-next-auth.session-token,
  • Session
    这个是js中const {data,status}=useSession();中使用的数据。它代表的是js 中的对象。

Session 的获取过程

当在client端调用getSession(),它其实是发请求去/api/auth/session,这个API会从你的cookie 中读取Token,然后解析,接着分别调用AuthOption里面callback 里的jwt(),session()两个回调函数。然后将返回的新的session 对象放到body里面,将更新过的Token塞回cookie,交给客户端。

js 中的session 对象跟 cookie 里面的Token 有什么关系。

我们可以模糊的认为,cookie 里面的Token 就是jwt()回调函数的返回值,加密后存储到cookie里面。而session()回调函数的返回值就返回到前端的session JS 对象中。

Token 与 Session 的同步问题

由于同一个Token在前端有两种形态的存在,也就是cookie 与Session 对象。那么就有很大的可能会出现不同步的情况(例如,cookie 过期了,session 对象还在)。大多数的情况下,前端的Session 是借助与SessionProvider 来实现的。借助这个我们可以使用useSession()的方式来实现session 的共享。

  • next-auth\react里面的SessionProvider, 内部其实是引用了SessionContext,它来给这个Context 提供了数据源。在这个组件首次加载的时候,它会通过getSession()方法获取到最新的session,同时这个过程也会更新cookie。为了更新这个Session对象。其实const {data,status,update}=useSession(),在客户端它放出了第三个参数,当我们调用这个方法是update(newSession|null),我们就可以完成一次session对象的更新与获取过程。
  • 除此之外,它还提供了另外两种途径,
    • 第一,监听了document 的visibilitychange事件,每次窗口被激活后,都会激发session 的刷新。这个是通过refetchOnWindowFocus控制
    • 第二,轮询,refetchInterval 通过这个参数提供时间间隔,定期去刷session。
    • 第三,这个就比较歪门邪道了,通过修改localStorage里面的nextauth.message这个值,也可以触发。例如
    const message={event:'session'}
    localStorage.setItem('nextauth.message',JSON.stringify({ ...message, timestamp: now() }));
    

SessionProvider

这个组件所在的next-auth\react中还额外提供了一些有用的方法,

useSession

const {data,status,update}=useSession(),这个方法其实基本上就是把useContext(SessionContext)

getSession

这个方法是客户端发请求去/api/auth/session这个api 获取session, 注意,这个会返回最新的Session,但是不会更新SessionContext 里面的值。

getCsrfToken

这个方法是用于获取CsrfToken,它其实是访问/api/auth/csrf这个API,获取csrftoken,除了在body中返回csrftoken,它也会降该值写入到cookie中。我一开始有个疑惑,如果csrfToken都写入到cookie中了,那么就失去了csrf的意义了。后来看了源码后发现,对于/api/auth下面的所有POST请求,必须在body中也提供这个csrfToken,后端会依据cookie里面的跟body里面的进行比对。这边简单介绍一下原理。Cookie里面的csrf有两部分组成csrfToken|hash,body里面或者getCsrfToken返回的则是前面的csrfToken这部分,这个csrfToken就是一个简单的32位的随机数。当验证csrfToken的有效性的时候,它会先从cookie里面读取这个cookie,用自己的密钥计算一下csrfToken产生的hash,如果csrfToken有效,则用它与body里面的csrfToken进行比对。这么做的好处是,后端不用管理这个csrfToken。

export function createCSRFToken({
  options,
  cookieValue,
  isPost,
  bodyValue,
}: CreateCSRFTokenParams) {
  if (cookieValue) {
    const [csrfToken, csrfTokenHash] = cookieValue.split("|")
    const expectedCsrfTokenHash = createHash("sha256")
      .update(`${csrfToken}${options.secret}`)
      .digest("hex")
    if (csrfTokenHash === expectedCsrfTokenHash) {
      // If hash matches then we trust the CSRF token value
      // If this is a POST request and the CSRF Token in the POST request matches
      // the cookie we have already verified is the one we have set, then the token is verified!
      const csrfTokenVerified = isPost && csrfToken === bodyValue

      return { csrfTokenVerified, csrfToken }
    }
  }

  // New CSRF token
  const csrfToken = randomBytes(32).toString("hex")
  const csrfTokenHash = createHash("sha256")
    .update(`${csrfToken}${options.secret}`)
    .digest("hex")
  const cookie = `${csrfToken}|${csrfTokenHash}`

  return { cookie, csrfToken }
}

signIn

这个方法是用于登录的,如果我们提供了provider,作为参数,那么它会开启一个登录的流程。例如azureb2c, 它会开启b2c 登录的流程,登录完成后,它会同时触发getSession的逻辑。完成后,前端cookie里面拥有了cookie,js 里面拿到了session 对象

signOut

这个方法主要是用于清除完前端的cookie.清除完后可以跳转其他的页面。

顺带聊一下Cookie 参考

虽然经常被人诟病,但是这个真心是个好东西,用起来省心。之所以被诟病的原因,主要还是安全的问题。CSRF的问题。但是如果不考虑兼容性,最新版的浏览器对于它的安全保证还是非常高的。例如

  • HttpOnly
    这个属性可以确保js 无法读到这个cookie,通过document.cookies
  • Security
    这个确保只有https的连接才能读取
  • Samesite
    有效值 Strict, Lax, None
    Strict: 最严格的模式,只有当前域名,当前的tab的请求才会带上cookie.
    Lax: 比Strict 要宽松一点,除了这些例外, 其他的跟Strict 一样。Form 的Get 请求,Link标签里面的路由,或者预加载。会带上cookie,其他的就跟Strict 一样了。
    None:没有同源的限制。

标签:这个,const,里面,Auth,Next,session,cookie,csrfToken,NextJs
From: https://www.cnblogs.com/kongshu-612/p/17571781.html

相关文章

  • Atcoder Regular Contest 124 E - Pass to Next
    首先第一步是一个浅显的观察:我们要求的是所有可能的最终序列的贡献之和,如果能改为计算所有操作序列的贡献之和那问题会简单很多,并且我们惊奇地发现,如果一组\(x_i\)全大于\(0\),那么把它们全减去\(1\)以后得到的答案序列不会改变,而对于任意一种可能的最终序列,必然存在一组\(\m......
  • openid connect vs oauth
    AnswerfromChatGPTOpenIDandOAutharerelatedbutdistinctprotocolsthatservedifferentpurposesinthecontextofwebauthenticationandauthorization. OAuth(OpenAuthorization):OAuthisanopenstandardforaccessdelegation.Itallowsauser(......
  • 身份验证遇到问题,登陆ChatGPT时提示:“we ran into an issue while authenticating you
    oops!weranintoanissuewhileauthenticatingyou,ifthisissuepersists,pleasecontactusthroughourhelpcenterathelp.openai.com说明:哎呀!我们在验证您的身份时遇到了一个问题,如果这个问题仍然存在,请通过help.openai.com的帮助中心与我们联系看到这个错误时,一般都......
  • linux awk 命令中 next 和 getline
     001、continue[root@PC1test01]#lsdata[root@PC1test01]#catdata##测试数据1000naughty500cc400zoer100[root@PC1test01]#awk'{if(NR==2){next};print$0}'data##next相当于内层循环的continue,表示跳过该次迭代1000cc400zoer100......
  • Spring Authorization Server (三)客户端搭建
    在上一篇中,我们介绍了认证服务器的搭建,由于我们没有自己的客户端回调地址,在测试过程中,我们是使用http://www.baidu.com作为回调地址,获取到授权码code后,再使用postman去获取令牌信息的。在本篇中,我们将搭建自己的客户端,实现连贯的令牌获取操作,操作流程如下。场景类比假设我们公司的......
  • Nest.js框架下,nest g app auth 命令报错!
    首先报错信息是:Failedtoexecutecommand:node@nestjs/schematics:sub-app--name=auth--no-dry-run--no-skip-import--language="ts"--source-root="apps/reservations/src"--spec--no-flat--spec-file-suffix="spec",大概的意思就是无法执行这条命令。......
  • 魔法方法之__iter__(self) && __next__(self)
    __iter____iter__(self)是一个特殊方法,用于返回一个迭代器对象,使得自定义的类可以支持迭代操作。最佳实践:在自定义类中实现 __iter__() 方法时,应该返回一个迭代器对象,通常是自身的实例。迭代器对象应该实现 __next__() 方法,用于返回容器中的下一个元素,并在没有更多元素......
  • eclipse修改默认的author
    之前每次都会修改Java的类注释。类似这样的/***@author作者E-mail:*@version创建时间:${date}${time}*类说明*/ 今天遇到1种情况,原有作者已经有了,只想加上自己的名字。习惯性尝试用java文档@提示,看到有@author结果显示的是Leiwen。实际上想用的是公司邮箱......
  • xauth
    xauth显示和编辑被用于连接X服务器的认证信息补充说明xauth命令用于显示和编辑被用于连接X服务器的认证信息。语法xauth(选项)(参数)选项-f:不使用默认的认证文件,而使用指定的认证文件;-q:安静模式,不打印未请求的状态信息;-v:详细模式,打印指定的各种操作信息;-i:忽略认证文件......
  • Docker部署nextcloud及其使用方法
    Docker部署Nextcloud及其使用方法Docker安装Docker是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0协议开源。Docker可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。容器是完全使用沙箱机......