Kentico 12 MVC User Authentication

Jon Bowen asked on October 3, 2019 16:29

I'm using Identity Framework for user authentication as described here. When the user enters a wrong password, the method SignInManager.PasswordSignInAsync is throwing an error stating the IncrementAccessFailedCountAsync method is not implemented. Any help would be greatly appreciated.

Thanks in advance

Recent Answers


Eric Dugre answered on October 4, 2019 21:17

Hello Jon,

How is your authentication initialized? Have you made an changes to the UserManager?

By default, user lockout is disabled in our UserManager. The IncrementAccessFailedCountAsync() is indeed not implemented, but it also shouldn't be triggered by default.

0 votesVote for this answer Mark as a Correct answer

Jon Bowen answered on October 7, 2019 13:25

I was making the call to authenticate users this way

SignInManager.PasswordSignInAsync(model.Email, model.Password, false, true);

The last boolean parameter was set to true, causing the exception when the credentials were wrong. Changing to false stopped the exceptions, but it is frustrating that account lockout isn't implemented by default. I didn't see a way to override IncrementAccessFailedCountAsync in a derived UserManager or SignInManager class. What is the recommended way to implement account lockout?

0 votesVote for this answer Mark as a Correct answer

Kevin Spencer answered on October 24, 2019 15:31

I am also having this issue. Is there any guidance for MVC?

0 votesVote for this answer Mark as a Correct answer

Dominic Boyer answered on July 27, 2020 17:56

any solution ? have the same problem

0 votesVote for this answer Mark as a Correct answer

Jon Bowen answered on July 30, 2020 15:14

This is what I ended up doing in the Login action method in the Account Controller. I increment the Invalid Logon Attempts count myself and check for that to show the correct error message. Here is a code snippet to help out.

var user = UserInfoProvider.GetUserInfo(model.Email);
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, false, false);
switch (result)
{
    case SignInStatus.Success:
        Session.Clear();

        // Reset the invalid logon attempt count since the login was successful
        user.UserInvalidLogOnAttempts = 0;
        user.Update();

        // Redirect the user to the desired page
        Response.Redirect("~/");
        break;

    case SignInStatus.LockedOut:
        // Tell the user they are locked out.
        TempData["Msg"] = "Your account is locked out";
        break;

    case SignInStatus.Failure:
    default:
        // Increment the number of invalid logon attempts.
        ++user.UserInvalidLogOnAttempts;
        user.Update();

        // Tell the user what happened. Change 5 to your number of invalid login attempts or retrieve from settings.
        TempData["Msg"] = user.UserInvalidLogOnAttempts < 5 ? "Invalid Credentials" : "Your account is locked out";
        break;
}
1 votesVote for this answer Mark as a Correct answer

Dominic Boyer answered on July 30, 2020 15:45

Thank you Jon, i will try to implement your method :) cause i try several other one, and nothing seem to work.

0 votesVote for this answer Mark as a Correct answer

Dominic Boyer answered on August 3, 2020 22:24

Question Jon, how do the "user" unlocked the account after that, did you put a timer or something like that ? thank you

0 votesVote for this answer Mark as a Correct answer

Jon Bowen answered on August 4, 2020 02:58 (last edited on August 4, 2020 02:59)

0 votesVote for this answer Mark as a Correct answer

Dominic Boyer answered on August 4, 2020 14:58

ok thank you i have already implement this feature :)

0 votesVote for this answer Mark as a Correct answer

Dominic Boyer answered on August 7, 2020 15:33 (last edited on August 7, 2020 15:42)

I implement the user.UserInvalidLogOnAttempts in the login action, after 5 failed attempts, i disabled the user user.Enabled = false, and then on the forgotpassword / resetpassword page after the user received the url with the token to change is password i enabled the user user.Enabled = true and reset to 0 the user.UserInvalidLogOnAttempts.

Login action:

// Attempts to authenticate the user against the Kentico database
        SignInStatus signInResult = SignInStatus.Failure;
        try
        {
            signInResult = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.SignInIsPersistent, false);
        }
        catch (Exception ex)
        {
            // Logs an error into the Kentico event log if the authentication fails
            EventLogProvider.LogException("AccountController", "Login", ex);
        }

        // Get the user info
        var user = UserInfoProvider.GetUserInfo(model.UserName);           

        //If the authentication was not successful, displays the sign-in form with an "Authentication failed" message
        if (signInResult != SignInStatus.Success)
        {
            // Increment the number of invalid logon attempts.
            ++user.UserInvalidLogOnAttempts;
            user.Update();

            if (user.UserInvalidLogOnAttempts >= 5 || user.Enabled == false)
            {
                user.Enabled = false;
                user.Update();
                string errorMessageLocked = "Your account is disabled, please reset your password by clicking forgot password";
                ModelState.AddModelError(string.Empty, errorMessageLocked);
            }
            else
            {
                string errorMessageFailed = "Authentication Failed" + " - " + user.UserInvalidLogOnAttempts + "/5 attempts";
                ModelState.AddModelError(string.Empty, errorMessageFailed);
            }                

            return View();
        }

        // Reset the invalid logon attempt count since the login was successful
        user.UserInvalidLogOnAttempts = 0;
        user.Update();

        return RedirectToAction("...");

and in the resetpassword action:

if (ResetUserPassword(model.UserID, model.Token, model.Password).Succeeded)
        {
            // Get the user info, reset the invalid logon attempt count and enable the account
            var user = UserInfoProvider.GetUserInfo(model.UserID);
            user.Enabled = true;
            user.UserInvalidLogOnAttempts = 0;
            user.Update();

            return RedirectToAction("ResetPasswordSucceeded");
        }
0 votesVote for this answer Mark as a Correct answer

   Please, sign in to be able to submit a new answer.