0

我最近遇到了下面的 Microsoft.Identity 类,它可以用作向登录的用户提供 2FA 生成和验证的一种方式,作为第二因素保护。我想知道是否有人找到了比以下示例更好的类或库或代码实践?

https://github.com/aspnet/Identity/blob/master/src/Core/AuthenticatorTokenProvider.cs

特别有问题的代码:

public virtual async Task<bool> ValidateAsync(string purpose, string token, UserManager<TUser> manager, TUser user)
    {
        var key = await manager.GetAuthenticatorKeyAsync(user);
        int code;
        if (!int.TryParse(token, out code))
        {
            return false;
        }

        var hash = new HMACSHA1(Base32.FromBase32(key));
        var unixTimestamp = Convert.ToInt64(Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds));
        var timestep = Convert.ToInt64(unixTimestamp / 30);
        // Allow codes from 90s in each direction (we could make this configurable?)
        for (int i = -2; i <= 2; i++)
        {
            var expectedCode = Rfc6238AuthenticationService.ComputeTotp(hash, (ulong)(timestep + i), modifier: null);
            if (expectedCode == code)
            {
                return true;
            }
        }
        return false;
    }

我对上面的脚本不满意的原因是因为这个代码(据我测试过)不是一次性使用的,并且设置允许用户输入旧代码(在这个例子中最多 89 秒) ,如果i在这种情况下将变量更改为 0,则意味着代码仅在 30s 内有效timestep

变量(在timestep这种情况下)每 30 秒实时更新一次。因此,在 12:01:40,您可能已收到验证码,但这可能在 30 秒内“无效”,它仅在 19 秒内有效,直到下一个 30 秒timestep更新。

您可能会争辩将时间步长增加到 3 分钟,但无论如何它仍然可能让用户在下一次timestep更新之前请求代码。

4

1 回答 1

0

通过一些挖掘工作,Microsoft 带来了这种“TOTP”2fa 方法,它使用 Time 作为生成这些代码的方式,以及其他修饰符,如你的 securitystamp 和 hash。

我发现的解决方案是保留此实现,但一旦用户成功验证,就更新用户 SecurityStamp,这也意味着必须刷新登录 cookie。(因为登录 cookie 使用 SecurityStamp 生成,并且验证方式相同)

最好我会偏离这个实现,而是使用更强大的标准(正确的 OTP),但是这个解决方案有效并且仍然是一种有效的安全方法。

于 2021-04-22T09:38:30.730 回答