2016-07-12 2 views
1

Ich möchte meine MVC-Anwendung so konfigurieren, dass Benutzer zufällig mit einer 2-Faktor-Authentifizierung bei 1-in-N-Besuchen auf der Website befragt werden.Kann ASP.NET OWIN so eingestellt werden, dass Benutzer in zufälligen/gelegentlichen Intervallen um einen 2FA-Code gebeten werden?

zu beginnen, ich tat dies nur als Teil des Login:

int challengeFrequency = Convert.ToInt16(ConfigurationManager.AppSettings["ChallengeFrequency"]); 
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: true); 
switch (result) 
{ 
    case SignInStatus.Success: 
     Random rnd = new Random(); 
     if(rnd.Next(challengeFrequency) == 1) 
     { 
      if (!await SignInManager.SendTwoFactorCodeAsync("Phone Code")) 
      { 
       return RedirectToAction("Error"); 
      } 
      return RedirectToAction("VerifyCode", new { Provider = "Phone Code", ReturnUrl = returnUrl, RememberMe = model.RememberMe }); 
     } 
     return RedirectToLocal(returnUrl); 
    // other cases 
} 

Aber es durchsickert ich den Prozess falsch verstanden habe, und dass PasswordSignInAsync wird nicht aufgerufen, wenn der Benutzer ein gültiges Cookie hat für der Standort. Ich habe geplant, diese Einstellungen zu ändern, so dass die Benutzer in jeder Zeit in jedem Fall zu unterschreiben hatten, so in Startup.Auth fügte ich hinzu:

app.UseCookieAuthentication(new CookieAuthenticationOptions 
{ 
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, 
    LoginPath = new PathString("/Account/Login"), 
    SlidingExpiration = true, 
    ExpireTimeSpan = TimeSpan.FromSeconds(5), 
    Provider = new CookieAuthenticationProvider 
    { 
     OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
      validateInterval: TimeSpan.FromSeconds(0), 
      regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager)) 
    } 
}); 

So, jetzt Benutzer jedes Mal herausgefordert. Aber natürlich erhalten wir ohne Cookie kein SignInStatus.Success-Ergebnis, und der Benutzer wird immer sowohl für das Passwort als auch für einen 2FA-Code herausgefordert.

Wie kann ich den Prozess unterbrechen, um sicherzustellen, dass sich der Benutzer immer mit einem Passwort anmelden muss, aber nur gelegentlich nach einem 2FA-Code gefragt wird?

+0

Nizza Lösung, aber vielleicht sind Sie besser dran mit etwas etwas anders? Also fragen Sie bei jeder 10. Anmeldung, oder können Sie eine Markierung für den Benutzer setzen, dass die nächste Anmeldung 2FA verwenden muss. Auf diese Weise erhalten Sie ein wenig mehr Kontrolle und Sie sind nicht in einer Situation, in der der Benutzer möglicherweise nie 2FA Überprüfung benötigt (Wahrscheinlichkeit ist Spaß so!) – DavidG

+0

@DavidG Oh sicher - ich war nur auf der Suche nach der Knochenmechanik von Wo kann ich den normalen Login-Prozess stoppen, um das zu erleichtern, was ich tun möchte? Die Antwort ist, Ihren eigenen Code zu generieren, sich direkt damit einzuloggen und das Senden an den Benutzer zu umgehen. Jetzt habe ich, dass ich eine statistisch interessantere Methode der Stichprobenziehung für mich selbst erarbeiten kann :) –

+1

Ich mag die Idee einer Flagge auf den Benutzer, um 2FA zu erzwingen. Auf diese Weise können Sie bei einem Sicherheitsproblem die Datenbank aktualisieren, um zu erzwingen, dass 2FA bei der nächsten Anmeldung verwendet wird. Du könntest auch einen Prozess haben, um es zu erzwingen, wenn du zu viele ungültige Passwortversuche etc. feststellst. OK, ich bin zu aufgeregt über dieses! – DavidG

Antwort

1

konnte ich diese schließlich durch eine Token on the fly zu erzeugen und es mit dem TwoFactorSignIn Verfahren zu erfüllen, etwa so:

int challengeFrequency = Convert.ToInt16(ConfigurationManager.AppSettings["ChallengeFrequency"]); 
var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: true); 
switch (result) 
{ 
    case SignInStatus.Success: 
     return RedirectToLocal(returnUrl); 
    case SignInStatus.RequiresVerification: 
     Random rnd = new Random(); 
     if (rnd.Next(1, challengeFrequency) == 1) 
     { 
      if (!await SignInManager.SendTwoFactorCodeAsync("Phone Code")) 
      { 
       return RedirectToAction("Login", "Account"); 
      } 

      return RedirectToAction("VerifyCode", new { Provider = "Phone Code", ReturnUrl = returnUrl, RememberMe = model.RememberMe }); 
     } 
     else 
     { 
      var token = await UserManager.GenerateTwoFactorTokenAsync(user.Id, "Phone Code"); 
      await SignInManager.TwoFactorSignInAsync("Phone Code", token, false, false); 
      return RedirectToLocal(returnUrl); 
     } 
    // other cases 
} 
Verwandte Themen