Javascript 保存OAuth2访问令牌以进行无会话身份验证

Javascript 保存OAuth2访问令牌以进行无会话身份验证,javascript,session,oauth,oauth-2.0,Javascript,Session,Oauth,Oauth 2.0,我设置了一个使用OAuth2密码授权身份验证的无会话应用程序。当用户使用用户名和密码登录我的应用程序时,我会保存30分钟内有效的访问令牌。我还保存了一个刷新令牌,以防我需要将会话延长30分钟以上。刷新令牌的有效期为30天 如果在登录时选中“记住我”复选框,我会将访问和刷新令牌保存在中,以便只要刷新令牌有效,它们就会一直存在 除了几个问题外,这两个问题似乎都很好: 如果浏览器保持打开状态且用户未注销,会话可能会持续30天 不会在窗口/选项卡之间持续存在,因此如果用户打开新窗口,他们需要再次登录。当

我设置了一个使用OAuth2密码授权身份验证的无会话应用程序。当用户使用用户名和密码登录我的应用程序时,我会保存30分钟内有效的访问令牌。我还保存了一个刷新令牌,以防我需要将会话延长30分钟以上。刷新令牌的有效期为30天

如果在登录时选中“记住我”复选框,我会将访问和刷新令牌保存在中,以便只要刷新令牌有效,它们就会一直存在

除了几个问题外,这两个问题似乎都很好:

  • 如果浏览器保持打开状态且用户未注销,会话可能会持续30天
  • 不会在窗口/选项卡之间持续存在,因此如果用户打开新窗口,他们需要再次登录。当选中“记住我”复选框时,这不是一个问题,因为在窗口之间确实存在

  • 我认为使用刷新令牌对于JavaScript应用程序是不安全的——您需要访问
    /token
    端点,并使用应用程序的机密进行身份验证。但在这样的应用中,秘密会被公开

    我更喜欢OAuth2隐式流,并使用
    prompt=none
    参数(从OpenID Connect)从
    /auth
    端点获取新令牌。但是对于隐式流,您可能需要获得一个寿命更长的ID令牌(稍后使用ID令牌请求访问令牌),或者在OAuth2上实现“记住我”(更好的选项——可以由任何应用程序使用)。这也解决了标签之间传递令牌的问题2

  • “会话”是指使用刷新令牌生成30天的访问令牌?如果这是一个问题,您可以实现一些活动检测器,如果在30分钟内没有活动,该检测器会将用户注销
  • 可以将
    localStorage
    用作一种消息传递服务,因此您可以将令牌保存在
    sessionStorage
    中,但新选项卡可以使用
    localStorage
    从现有选项卡请求令牌。有关更多信息,请参阅
  • 链接文章中的代码示例:

    function eventListener(e) {
        if (e.key == 'storage-event') {
            output.innerHTML = e.newValue;
        }
    }
    
    function triggerEvent() {
        localStorage.setItem('storage-event', this.value);
    }
    
    window.addEventListener("storage", eventListener, true);
    data.addEventListener("keyup", triggerEvent, true);
    
    工作流程如下所示:

  • 打开新选项卡并将任意值写入localStorage,其中包含一个键,指示它需要令牌。钥匙可以是“新打开的”。新选项卡开始监听另一个键“oauth2token”的更改
  • 现有选项卡侦听“newTabOpened”键的更改,作为一种反应,它将其标记值写入“oauth2token”键下
  • 新选项卡读取令牌并将其从本地存储中删除

  • 我曾考虑使用localStorage在windows之间传递令牌,但这可能会导致无意中将访问/刷新令牌留在localStorage中。新选项卡可以在读取令牌后立即从
    localStorage
    中删除令牌。对,但问题是,您必须将它们放在localStorage中,以防打开新选项卡。但是如果一个新的标签从来没有打开过,那么它们就会在那里。我在答案中添加了一个localStorage操作步骤的列表。