使用Google身份验证器进行双因素身份验证 - 手动键入密钥而不是扫描QR码

时间:2017-11-13 15:15:17

标签: qr-code two-factor-authentication one-time-password google-authenticator totp

在Google身份验证器应用中,您可以扫描二维码或手动输入发卡行提供的密钥。

在以下屏幕截图中,您可以看到Google Security设置中的2FA设置,显示如何通过第二种方法获取TOTP。

Google 2FA settings - Google Authenticator setup

我的问题是:这个密钥是如何生成的?

我正在尝试使用Google身份验证器为我的网站支持2FA,我找到了很多关于如何生成QR码的参考和文档,但没有提到替代方法。

修改

为了更清楚一点,我在Grails 3 webapp中使用Google身份验证器支持2FA。我已经通过为每个用户生成一个密钥(Base32字符串)来实现整个用户流程,为用户扫描提供QR码,并在登录时验证TOTP。我用作依赖项:

  • org.jboss.aerogear:aerogear-otp-javaaerogear OTP方便地验证来自GA的TOTP的用户密钥
  • org.grails.plugins:qrcodeqrcode Grails plugin生成二维码

我的问题是关于在Google身份验证器应用中添加新条目的两种方法: 1.扫描二维码(我身边一切都好) 2.手动键入帐户名称和字母代码(在我的第一个屏幕截图中,代码在Google安全设置中提供)

你可以看到GA for Android的解释性截图:

Google 2FA settings - Google Authenticator setup

如何生成并提供此类代码(从第一个屏幕截图中的fzee开始,并在第二个屏幕中为用户命名为“提供密钥”)?我确定它是在QR码中编码的相同数据字符串的编码,但我不知道哪个(不仅仅是Base32)。

4 个答案:

答案 0 :(得分:2)

key = secret

密钥应与您生成的密钥相同。只需打开谷歌身份验证器并手动将其添加为密钥即可对其进行测试。

在以下链接中查看文档: https://support.google.com/accounts/answer/1066447?co=GENIE.Platform%3DiOS&hl=en

答案 1 :(得分:1)

Google身份验证器设置QR代码是基于一些事情生成的,其中一个是“密钥”,因此根据您用于构建到您网站的代码库,通常首先生成“密钥”然后使用该密钥生成QR码。

如果你看一下这个node.js模块,你可以看到我在说什么

// generate base32 secret
var secret = GA.encode('base 32 encoded user secret') || GA.secret();

// get QRCode in SVG format
var qrCode = GA.qrCode('akanass', 'otp.js', secret);

https://github.com/njl07/otp.js/#qrcode-generation

这是另一个可以手动生成QR码的示例网站, 您可以提供Label, User, Key and URL,然后生成QR码。

https://dan.hersam.com/tools/gen-qr-code.html

让我知道您尝试使用哪些代码库将其实现到您的网站中,然后我可以帮助您跟踪生成密钥的位置

答案 2 :(得分:0)

public class HomeController : Controller
    {
        private const string key = "key"; // any 10-12 char string for use as private key in google authenticator
        public ActionResult Login()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Login(LoginModel login)
        {
            string message = "";
            bool status = false;

            //check username and password form our database here
            //for demo I am going to use Admin as Username and Password1 as Password static value
            if (login.Username == "sanket" && login.Password == "123")
            {
                status = true; // show 2FA form
                message = "2FA Verification";
                Session["Username"] = login.Username;

                //2FA Setup
                TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
                string UserUniqueKey = login.Username + key; //as Its a demo, I have done this way. But you should use any encrypted value here which will be unique value per user 
                Session["UserUniqueKey"] = UserUniqueKey;
                var setupInfo = tfa.GenerateSetupCode("Sanket Security", login.Username, UserUniqueKey, 300, 300);
                ViewBag.BarcodeImageUrl = setupInfo.QrCodeSetupImageUrl;
                ViewBag.SetupCode = setupInfo.ManualEntryKey;
            }
            else
            {
                message = "Invalid credential";
            }
            ViewBag.Message = message;
            ViewBag.Status = status;
            return View();
        }

        public ActionResult MyProfile()
        {
            if (Session["Username"] == null || Session["IsValid2FA"] == null || !(bool)Session["IsValid2FA"])
            {
                return RedirectToAction("Login");
            }
            ViewBag.Message = "Welcome " + Session["Username"].ToString();
            return View();
        }
        public ActionResult Verify2FA()
        {
            var token = Request["passcode"];
            TwoFactorAuthenticator tfa = new TwoFactorAuthenticator();
            string UserUniqueKey = Session["UserUniqueKey"].ToString();
            bool isValid = tfa.ValidateTwoFactorPIN(UserUniqueKey, token);
            if (isValid)
            {
                Session["IsValid2FA"] = true;
                return RedirectToAction("MyProfile", "Home");
                token=string.Empty;
            }
            return RedirectToAction("Login", "Home");
        }
    }
}

答案 3 :(得分:0)

And View

@model _2FAGoogleAuthenticator.ViewModel.LoginModel

@{
    ViewBag.Title = "Login";
}

<h2>Login</h2>

@* Here we will add 2 form, 1 for Login and another one for 2FA token verification form *@
@if (ViewBag.Status == null || !ViewBag.Status)
{
    <!--Show login form here, Viewbag.Status is used for check is already veirfied from our database or not-->
    <div>@ViewBag.Message</div>
    <div>
        @using (Html.BeginForm())
        {
            <div class="form-group">
                <label for="Username">Username : </label>
                @Html.TextBoxFor(a => a.Username, new { @class = "form-control"})
            </div>
            <div class="form-group">
                <label for="Password">Password : </label>
                @Html.TextBoxFor(a => a.Password, new { @class="form-control", type="password"})
            </div>
            <input type="submit" value="Login" class="btn btn-default" />
        }
    </div>
}
else
{
    <!--Show 2FA verification form here-->
    <div>@ViewBag.Message</div>
    <div>
        <img src="@ViewBag.BarcodeImageUrl"/>
    </div>
    <div>
        **Manual Setup Code : @ViewBag.SetupCode**
    </div>
    <div>
        @using (Html.BeginForm("Verify2FA","Home", FormMethod.Post))
        {
            <input type="text" name="passcode" />
            <input type="submit" class="btn btn-success" /> 
        }
    </div>
}