aspnet / Identity

[Archived] ASP.NET Core Identity is the membership system for building ASP.NET Core web applications, including membership, login, and user data. Project moved to https://github.com/aspnet/AspNetCore
Apache License 2.0
1.96k stars 868 forks source link

Allow two-factor challenges at random intervals #1450

Closed mattthr closed 6 years ago

mattthr commented 7 years ago

Some sites which use two factor authentication - Steam is a good example - do not challenge the user for the authentication code on every visit. This retains many of the advantages of increased security but is less inconvenient for the user.

As far as I can tell, Asp.Net identity does not support this out of the box. I tried to roll my own version:

var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: true);
switch (result)
{
    // other cases
    case SignInStatus.RequiresVerification:
        int challengeFrequency = Convert.ToInt16(ConfigurationManager.AppSettings["ChallengeFrequency"]);
        Random rnd = new Random();
        if (rnd.Next(1, challengeFrequency + 1) == 1)
        {
            return RedirectToAction("SendCode", new { returnUrl = returnUrl });
        }
        else
        {
            var token = await UserManager.GenerateTwoFactorTokenAsync(user.Id, "Phone Code");
            await SignInManager.TwoFactorSignInAsync("Phone Code", token, false, false);
            return RedirectToLocal(returnUrl);
        }
}

But this does not work, for reasons I've been unable to figure out - when triggered this code returns SignInStatus.Failure and puts the user back on the login screen, from where they will be logged on successfully if they submit a second time.

Regardless of my failures, I still think this would be a useful feature to add to the Identity framework.

blowdart commented 7 years ago

Yea, this isn't supported out of the box, because we view it as a bad idea security wise.

In your code you could call SignInManager.SigninAsync() if you decide you don't want to be secure.

grahamehorner commented 7 years ago

@blowdart would an option not be to create a policy that after a period of time the user is redirected to a two factor code verification screen, with the return uri of the page/action they came from ?

blowdart commented 7 years ago

No, because either someone is authorized, or not, not a half way in between.

grahamehorner commented 7 years ago

what I was thinking is like passport control, a person shows their passport and is allowed in and randomly gets checked by customs officials with additional checks; so authentication is the first step with a random second factor check, but I’ll defer to your security expertise if you feel it’s insecure or in appropriate

mattthr commented 7 years ago

That's a good analogy.

I understand the concern here about weakening the model, but it would be an option, down to the choice of the implementation to use full, occasional or no two-factor checks. And some site which encourage the use of two factor do carry out random spot checks rather than on every visit.

blowdart commented 7 years ago

It should be possible, an "upgrade", you'd override the forbidden page to prompt for extra auth, and if it works, add a new claim, but it's not something we'd do in the templates.