File: Pages\Account\Manage\EnableAuthenticator.cs
Web Access
Project: src\src\Identity\test\Identity.FunctionalTests\Microsoft.AspNetCore.Identity.FunctionalTests.csproj (Microsoft.AspNetCore.Identity.FunctionalTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Globalization;
using System.Net.Http;
using AngleSharp.Dom.Html;
 
namespace Microsoft.AspNetCore.Identity.FunctionalTests.Account.Manage;
 
internal class EnableAuthenticator : DefaultUIPage
{
    public const string AuthenticatorKey = nameof(EnableAuthenticator) + "." + nameof(AuthenticatorKey);
 
    private readonly IHtmlElement _codeElement;
    private readonly IHtmlFormElement _sendCodeForm;
 
    public EnableAuthenticator(
        HttpClient client,
        IHtmlDocument enableAuthenticator,
        DefaultUIContext context)
        : base(client, enableAuthenticator, context)
    {
        Assert.True(Context.UserAuthenticated);
        _codeElement = HtmlAssert.HasElement("kbd", enableAuthenticator);
        _sendCodeForm = HtmlAssert.HasForm("#send-code", enableAuthenticator);
    }
 
    internal async Task<ShowRecoveryCodes> SendValidCodeAsync()
    {
        var authenticatorKey = _codeElement.TextContent.Replace(" ", "");
        Context.AuthenticatorKey = authenticatorKey;
        var verificationCode = ComputeCode(authenticatorKey);
 
        var sendCodeResponse = await Client.SendAsync(_sendCodeForm, new Dictionary<string, string>
        {
            ["Input_Code"] = verificationCode
        });
 
        var goToShowRecoveryCodes = ResponseAssert.IsRedirect(sendCodeResponse);
        var showRecoveryCodesResponse = await Client.GetAsync(goToShowRecoveryCodes);
        var showRecoveryCodes = await ResponseAssert.IsHtmlDocumentAsync(showRecoveryCodesResponse);
 
        return new ShowRecoveryCodes(Client, showRecoveryCodes, Context);
    }
 
    public static string ComputeCode(string key)
    {
        var keyBytes = Base32.FromBase32(key);
        var unixTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
        var timestep = Convert.ToInt64(unixTimestamp / 30);
        var topt = Rfc6238AuthenticationService.ComputeTotp(keyBytes, (ulong)timestep, modifierBytes: null);
        return topt.ToString("D6", CultureInfo.InvariantCulture);
    }
}