停止刷新令牌的比赛条件?

时间:2019-05-10 17:49:24

标签: javascript c# reactjs authentication jwt

我有一个reactjs网站和asp.net核心后端,并且刷新令牌有问题。

当某人登录我的网站时,他们会获得访问令牌和刷新令牌(相当标准)。现在,我设置了一个比访问令牌的时间短的计时器。

当他们打开多个标签时,所有这些都很好用。问题在于它们都共享本地存储(需要自动登录,因此不能使用会话存储)

场景

2个选项卡一个接一个地打开。访问令牌死亡前2分钟设置2个计时器。

第一次触发第一次将刷新令牌发送到服务器,并带回新的刷新/访问令牌。在服务器上,发送的刷新令牌将被删除。

第2个计时器在第一个计时器(第一个计时器正在工作时)后不久触发,但是现在很有可能已删除刷新令牌,从而使该请求无效。

如何停止这种比赛状态?

var foundRefreshToken = dbContext.Tokens.FirstOrDefault(x => x.Value == refreshToken);

if (foundRefreshToken == null)
{
    return null;
}

var newRefreshToken = CreateRefreshToken(foundRefreshToken.ClientId, foundEmployee.Id);

dbContext.Tokens.Remove(foundRefreshToken);
dbContext.Tokens.Add(newRefreshToken);
dbContext.SaveChanges();


private Token CreateRefreshToken(string clientId, string userId)
    {
        return new Token()
        {
            ClientId = clientId,
            EmployeeId = userId,
            Value = GenerateRefreshToken(),
            CreatedDate = DateTime.UtcNow
        };
    }

// high level js
  refreshTimer;
  setRefreshTimer(intervals) {
    this.clearRefreshTimer();
    this.refreshTimer = setInterval(() => {
      this.refreshAuthentication();
    }, intervals);
  }

我能想到的仅有两件事是不要删除刷新令牌(但这会导致自动登录出现问题)

或者我在本地存储中有一个“锁定”第一个选项卡以进行刷新的标记,其他标记则等待查看是否执行该操作(猜测需要另一个计时器)。如果没有,那么下一个尝试。

还有其他想法吗?

2 个答案:

答案 0 :(得分:0)

当您创建令牌和刷新令牌时,两者都应具有一个到期日期,例如:

return new Token()
        {
            ClientId = clientId,
            EmployeeId = userId,
            Value = GenerateRefreshToken(),
            CreatedDate = DateTime.UtcNow,
            ExpirationDate = <you decide>
        };

在每个请求上,您都应该通过比较日期来检查令牌是否过期。如果已过期,则可以使用保持用户身份验证。最终,您甚至无法使刷新令牌过期,因为它必须由您的应用程序安全地存储。

刷新令牌和短期令牌背后的想法是,如果令牌被泄露,黑客只有10分钟的时间才需要刷新令牌来生成新令牌。

答案 1 :(得分:0)

最佳实践要求刷新令牌只能使用一次,并且每次使用新令牌时都应该使用。再次尝试使用旧的令牌应被视为是被盗的令牌-该用户的所有未完成的令牌应无效,任何新的访问尝试都需要完整登录。

当两个会话共享一个公共刷新令牌时(例如,在浏览器中打开两个选项卡并且该令牌存储在仅HTTP的cookie中时),就会发生竞争状态。当出现两个会话使用相同的刷新令牌同时尝试刷新的情况时,服务器的第一个会话将获得有效的新令牌,但是第二个会话发现它们的令牌现在无效并被注销。

如前所述,可以通过使用繁忙标志等机制在前端解决此问题,以便必须先完成第一次刷新,然后才能进行第二次刷新。

在后端,您可以使用一种机制,允许刷新令牌在完全失效或删除之前的很短时间内(仅几秒钟)重用。