Unlock user account

Hi all, I read and tested about the user lock feature using MaxLoginAttempts… I know that in order to re-enable locked users I should reset InvalidLoginAttempts to 0 and LockedDate to NULL.
If I want to, for example, re-enable the user after 5 min, where should I implement this feature?

You would need to override the existing AuthProvider.IsAccountLocked() implementation in your Custom Auth Provider and check the LockedDate for time elapsed.

Excuse me mythz… I have to override:

public class CustomAuthProvider : AuthProvider

or

public class CustomAuthProvider : CredentialsAuthProvider

?

All AuthProviders inherit from AuthProvider already so just inherit the AuthProvider you’re using, i.e. CredentialsAuthProvider if that’s what you’re using.

Thank you for your help mythz!
Everything in ServiceStack is pretty easy after your advices!

1 Like

Just another thing… would it be possible to override the TryAuthenticate function to check IsAccountLocked before the if (authRepo.TryAuthenticate(userName, password, out userAuth)) ?

(here is the line: https://github.com/ServiceStack/ServiceStack/blob/master/src/ServiceStack/Auth/CredentialsAuthProvider.cs#L54)

…it would be more consistent inform the user about his/her locked account, before he/she can submit the right password…

I’ve tried to accomplish it but I don’t know how to initialize userAuth without run authRepo.TryAuthenticate(userName, password, out userAuth before.

You can override the existing impl in your Custom provider to change it to work how you want, but note that this is still an “authentication attempt” so the user would have to still have submitted their password. You would need to query the UserAuth table directly and check the LockedDate when displaying the Login form (after somehow capturing the UserName before the password).

I think I found a solution just after submit my post! :sweat_smile:

public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
    var authRepo = authService.TryResolve<IAuthRepository>().AsUserAuthRepository(authService.GetResolver());
    var userAuth = authRepo.GetUserAuthByUserName(userName);

    if (userAuth == null)
        throw HttpError.Unauthorized(ErrorMessages.InvalidUsernameOrPassword);

    if (IsAccountLocked(authRepo, userAuth))
        throw new AuthenticationException("This account has been locked");

    if (authRepo.TryAuthenticate(userName, password, out userAuth)) return true;
        return false;
    }

Could be a decent solution?

I still don’t know what problem this is meant to solve? The User is still logging in with their Password but are now getting a User Account Locked message whether their password is right or wrong? I don’t understand how this improves UX or what the goal is?

If anything this leaks some user information as others can now tell whether another users account is locked or not without needing to know their password.

Mm… no… my TryAuthenticate returns the “Account Locked” message as soon as the user reach the MaxLoginAttempts!

With the default ServiceStack TryAuthenticate I always get the “Invalid UserName or Password” even if the account is already locked… to get the “Account Locked” message I should submit the right password.

I don’t know if I explained the problem… maybe it’s just me that I expect a different response… I could try to make you a video to better explain what I mean…

Yes… the downside of my solution is that others can tell if a user is locked or not by his/her UserName.

I think we’ve said the same thing, namely:

  • Users still need to supply UserName / Password
  • If Account is locked they’ll now receive the Account Locked error message regardless if they provide a correct password or not

So the only use-case this affects is when they supply an incorrect password? where now they’ll receive a Account Locked error message instead of an incorrect password error?

1 Like

Yep mythz! it’s correct!