c# - "Google Two Factor Authenticator"accountSecretKey 是否应该存储到我的数据库中?

标签 c# two-factor-authentication google-authenticator authenticator google-2fa

我正在尝试了解 Google 双因素身份验证器流程的工作原理,以便将其合并到我的网站中。据我了解,该过程有两个不同的部分

  1. 我网站上的一位用户启用了 2FA,这在我的用户和应用程序之间创建了链接。这是一次性步骤,不会在每次登录尝试时发生。
  2. 用户每次登录时,都需要提供来自 Google 身份验证器应用的六位数代码。

现在,使用以下代码生成 QR 图像和设置代码以启用 2FA 并将帐户链接到 Google Authenticate。

TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
string accountSecretKey = Guid.NewGuid();
var setupInfo = tfa.GenerateSetupCode("Dotnet Awesome", login.Username, accountSecretKey, 300, 300);
ViewBag.BarcodeImageUrl = setupInfo.QrCodeSetupImageUrl;
ViewBag.SetupCode = setupInfo.ManualEntryKey;

现在,对于每个请求,我都会使用以下代码对用户进行身份验证

TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
tfa.ValidateTwoFactorPIN(accountSecretKey, "Six Digit Code");

问题

在上面的代码中,accountSecretKey 代码是否需要保存到我的数据库中,以便我每次想要验证时都可以传递它?或者,我每次登录尝试时都必须重新创建的 accountSecretKey ?如果我要将这段代码存储到数据库中,是否也应该像密码一样对其进行加密?

最佳答案

当我设置它时,我倾向于:

数据库中有一个 G2FAEnabled 列,还有一个用于用户的 SecretKey

生成一个唯一的 key 并使用它为用户正在使用设置的 G2FA 的页面生成条形码,将其记住在服务器端(将其放入数据库中)但不要设置启用列

要求用户在将您的网站添加到身份验证器后扫描或键入其设备显示的代码。这证明他们的设备设置正确,设备时钟正确等

如果他们输入的数字正确,请将启用的列设置为 true 并锁定内容,以便 key 现在无法更改(更改它会杀死他们的 2FA)

从那时起,用户必须为当前服务器时间和存储在服务器上的 key 提供正确的基于时间的 PIN。他们的设备时钟必须与服务器保持同步。您可以通过检查当前时间两侧的 6 次来尝试找到匹配项,从而实现时钟漂移的容忍度(这意味着设备时钟可以相对于服务器时间正负 3 分钟并且仍然匹配)。

任何停用 2FA(将启用列设置为 false)的尝试都应该需要有效的 2FA 代码,但您的客户服务部门的替代流程(例如查看用户的护照)应该允许在不知情的情况下进行重置

您不必加密数据库中的 key - 您必须解密它才能使用它,并且它不像存储明文密码之类的失礼行为(如果您的数据库被盗,这是一个问题,因为用户始终重复使用密码,因此数据库被盗可能意味着您泄露了用户所有其他服务的密码),因为它应该是随机数据,不代表您组织之外的任何内容,因此不会帮助黑客破解进入使用相同 2FA 设备的另一个用户网站。

通常,如果有人能够窃取您的数据库,他们就已经达到了可以窃取必要位来解密您加密存储的任何内容的地步,但是如果您确定您的数据库很可能被盗,但您的Web 服务器将保持安全,然后无论如何加密数据库数据

关于c# - "Google Two Factor Authenticator"accountSecretKey 是否应该存储到我的数据库中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66322174/

相关文章:

django - Google Authenticator (Android) + Django 即使在时间同步之后也说无效 token

php - Google 身份验证器扫描时条形码无效

okta - 可以编写 Google 身份验证器代码脚本

c# - 使用 ashx 用 html 填充 div

c# - 获取逻辑驱动器列表

c# - 使用 mvc 身份注册电话号码而不是电子邮件

android - 谷歌验证器刮刮码

c# - 为什么 Entity Framework 为非常相似的代码创建不同的 sql 查询

c# - 通过 DNS.GetHostEntry 将 IP 地址转换为主机名

ios - 如何将 OTP 从用户的消息框直接填充到 iPhone 中的应用程序?