Exemple #1
0
        public async Task <IActionResult> EnableAuthenticator(EnableAuthenticatorViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return(View(model));
            }

            var id = User?.FindFirstValue("sub");

            string accessToken = await GetAccessToken();

            EnableAuthenticator contentModel = new EnableAuthenticator
            {
                Id = id,
                AuthenticatorUri = model.AuthenticatorUri,
                Code             = model.Code,
                SharedKey        = model.SharedKey,
            };

            string        asJson  = JsonSerializer.Serialize <EnableAuthenticator>(contentModel);
            StringContent content = new StringContent(asJson, Encoding.UTF8, "application/json");

            HttpClient client = _httpClientFactory.CreateClient("IdApiAccount");

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, $"{_configuration["AppURLS:IdApiBaseUrl"]}/api/v1/Account/EnableAuthenticatorAsync")
            {
                Content = content
            };

            using HttpResponseMessage response = await client.SendAsync(request);

            if (!response.IsSuccessStatusCode)
            {
                string badResponse = await response.Content.ReadAsStringAsync();

                ResponsePayload badResponseObj = JsonSerializer.Deserialize <ResponsePayload>(badResponse);
                if (badResponseObj.StatusCode == 400)
                {
                    ModelState.AddModelError("Code", "Verification code is invalid. Please scan the QR Code or enter the above Verification Code Key. Then use the One-Time password code generated by the Authenticator App to verify and complete 2FA set up.");
                    return(View(model));
                }

                _logger.LogError("~/Account/EnableAuthenticator(EnableAuthenticatorViewModel) - Error from IdApi - {0}", badResponseObj);
                TempData["ErrorMessage"] = "An error occurred while setting up your account for 2 factor authentication.";
                return(RedirectToAction(nameof(Index)));
            }

            string responseObj = await response.Content.ReadAsStringAsync();

            EnableAuthenticatorViewModel responseModel = JsonSerializer.Deserialize <EnableAuthenticatorViewModel>(responseObj);

            response.EnsureSuccessStatusCode();

            _logger.LogInformation("User with id:{0} has enabled 2FA with an authenticator app.", id);

            return(View("ShowCodes", responseModel));
        }
        public async Task <IActionResult> LoadSharedKeyAndQrCodeUriAsync([FromBody] string userId)
        {
            ApplicationUser user;

            try
            {
                user = await _userManager.FindByIdAsync(userId);

                if (user == null)
                {
                    _logger.LogError("~/Account/LoadSharedKeyAndQrCodeUriAsync(userId) - Could not find User Id:{0}. Unable to generate shared key and QR codes.", userId);
                    return(NotFound(new ApiResponse(404, $"~/Account/LoadSharedKeyAndQrCodeUriAsync(userId) - Could not find User Id:{userId}. Unable to generate shared key and QR codes.")));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError("UserManger encountered an error connecting to the database. Error:{0}", ex);
                return(StatusCode(503, new ApiResponse(503, "Error connecting to the database.")));
            }

            string unformattedKey;

            try
            {
                await _userManager.ResetAuthenticatorKeyAsync(user);                //reset Authenticator Key - there maybe a stale Authenticator Key from previous enable/disable 2fa

                unformattedKey = await _userManager.GetAuthenticatorKeyAsync(user); //For some reason, calling this method without calling ResetAuthenticatorKeyAsync first, returns null. Find time to understand why.

                if (String.IsNullOrWhiteSpace(unformattedKey))
                {
                    _logger.LogError("~/Account/LoadSharedKeyAndQrCodeUriAsync(userId) - _userManager encountered an error Getting Authenticator Key Async.");
                    return(StatusCode(500, new ApiResponse(500, "An internal error occurred enabling Multi-Factor Authentication.")));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError("~/Account/LoadSharedKeyAndQrCodeUriAsync(userId) - UserManger encountered an error connecting to the database. Error:{0}", ex);
                return(StatusCode(503, new ApiResponse(503, "Error connecting to the database.")));
            }

            EnableAuthenticator responseObj = new EnableAuthenticator
            {
                SharedKey        = FormatKey(unformattedKey),
                AuthenticatorUri = GenerateQrCodeUri(user.Email, unformattedKey),
            };

            string response = JsonSerializer.Serialize <EnableAuthenticator>(responseObj);

            return(Ok(response));
        }
Exemple #3
0
    internal async Task <Index> Send2FACodeAsync(string twoFactorKey)
    {
        var code = EnableAuthenticator.ComputeCode(twoFactorKey);

        var response = await Client.SendAsync(_twoFactorForm, new Dictionary <string, string>
        {
            ["Input_TwoFactorCode"] = code
        });

        var goToIndex = ResponseAssert.IsRedirect(response);

        Assert.Equal(Index.Path, goToIndex.ToString());
        var indexResponse = await Client.GetAsync(goToIndex);

        var index = await ResponseAssert.IsHtmlDocumentAsync(indexResponse);

        return(new Index(Client, index, Context.WithAuthenticatedUser()));
    }
        public async Task <IActionResult> EnableAuthenticatorAsync([FromBody] EnableAuthenticator model)
        {
            ApplicationUser user;

            try
            {
                user = await _userManager.FindByIdAsync(model.Id);

                if (user == null)
                {
                    _logger.LogError("~/Account/EnableAuthenticatorAsync(EnableAuthenticator) - Could not find User Id:{0}. Unable to generate shared key and QR codes.", model.Id);
                    return(NotFound(new ApiResponse(404, $"~/Account/EnableAuthenticatorAsync(EnableAuthenticator) - Could not find User Id:{model.Id}. Unable to generate shared key and QR codes.")));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError("UserManger encountered an error connecting to the database. Error:{0}", ex);
                return(StatusCode(503, new ApiResponse(503, "Error connecting to the database.")));
            }

            try
            {
                //Clean any whitespace in model.Code
                string verificationCode = model.Code.Replace(" ", string.Empty).Replace("-", string.Empty);
                bool   is2faTokenValid  = await _userManager.VerifyTwoFactorTokenAsync(user, _userManager.Options.Tokens.AuthenticatorTokenProvider, verificationCode);

                if (!is2faTokenValid)
                {
                    return(StatusCode(400, new ApiResponse(400, "Verification code is invalid. Please scan the QR Code or enter the above Verification Code Key. Then use the One-Time password code generated by the Authenticator App to verify and complete 2FA set up.")));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError("UserManger encountered an error connecting to the database. Error:{0}", ex);
                return(StatusCode(503, new ApiResponse(503, "Error connecting to the database.")));
            }

            try
            {
                IdentityResult TwoFactorResult = await _userManager.SetTwoFactorEnabledAsync(user, true);

                if (!TwoFactorResult.Succeeded)
                {
                    string errors = BuildErrorString(TwoFactorResult);
                    _logger.LogError("~/Account/EnableAuthenticator(EnableAuthenticatorViewModel) - userManager could not SetTwoFactorEnabledAsync for id:{0}'s account. Error:{1}", model.Id, errors);
                    return(StatusCode(500, new ApiResponse(500, "An error occurred setting 2FA for your account.")));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError("UserManger encountered an error connecting to the database. Error:{0}", ex);
                return(StatusCode(503, new ApiResponse(503, "Error connecting to the database.")));
            }

            IEnumerable <string> recoveryCodes;

            try
            {
                recoveryCodes = await _userManager.GenerateNewTwoFactorRecoveryCodesAsync(user, 10);

                if (!recoveryCodes.Any())
                {
                    _logger.LogError("~/Account/EnableAuthenticator(EnableAuthenticatorViewModel) - userManager could not GenerateNewTwoFactorRecoveryCodesAsync for id:{0}'s account.", model.Id);
                    return(StatusCode(500, new ApiResponse(500, "An error occurred setting 2FA for your account.")));
                }
            }
            catch (Exception ex)
            {
                _logger.LogError("UserManger encountered an error connecting to the database. Error:{0}", ex);
                return(StatusCode(503, new ApiResponse(503, "Error connecting to the database.")));
            }

            EnableAuthenticator responseObj = new EnableAuthenticator
            {
                Id = user.Id,
                AuthenticatorUri = model.AuthenticatorUri,
                Code             = model.Code,
                SharedKey        = model.SharedKey,
                RecoveryCodes    = recoveryCodes.ToArray(),
            };

            string response = JsonSerializer.Serialize <EnableAuthenticator>(responseObj);

            return(Ok(response));
        }