Microsoft Identity 更好地使用 AuthenticatorTokenProvider?

Posted

技术标签:

【中文标题】Microsoft Identity 更好地使用 AuthenticatorTokenProvider?【英文标题】:Microsoft Identity better use of AuthenticatorTokenProvider? 【发布时间】:2021-07-09 06:11:57 【问题描述】:

我最近遇到了下面的 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,则意味着代码仅在 timestep 的 30 秒内有效。

timestep 变量(在这种情况下)每 30 秒实时更新一次。所以在 12:01:40 你可能已经收到了一个验证码,但这可能在 30 秒内不是“有效”的,它只在 19 秒内有效,直到下一个 30 秒 timestep 更新。

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

【问题讨论】:

【参考方案1】:

通过一些挖掘工作,微软带来了这种“TOTP”2fa 方法,它使用时间作为生成这些代码的方式,以及其他修饰符,如您的安全标记和散列。

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

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

【讨论】:

以上是关于Microsoft Identity 更好地使用 AuthenticatorTokenProvider?的主要内容,如果未能解决你的问题,请参考以下文章

Microsoft.Identity Platform 登录循环

Microsoft.AspNetCore.Identity 与 Azure ActiveDirectory

模拟问题:无法实例化类的代理:Microsoft.AspNetCore.Identity.UserManager`

Microsoft.AspNet.Identity 的自定义成员身份 - CreateLocalUser 失败

从Microsoft.AspNet.Identity看微软推荐的一种MVC的分层架构

找不到包 Microsoft.AspNetCore.Identity.EntityFramework