Conferma dell'account e ripristino della password con identità ASP.NET (C#)

Prima di eseguire questa esercitazione, è necessario completare creare un'app Web di MVC 5 sicura ASP.NET con accesso, conferma tramite posta elettronica e reimpostazione della password. Questa esercitazione contiene altri dettagli e illustra come configurare la posta elettronica per la conferma dell'account locale e consentire agli utenti di reimpostare la password dimenticata in ASP.NET Identity.

Un account utente locale richiede all'utente di creare una password per l'account e tale password viene archiviata (in modo sicuro) nell'app Web. ASP.NET Identity supporta anche gli account di social networking, che non richiedono all'utente di creare una password per l'app. Gli account di social networking usano terze parti (ad esempio Google, Twitter, Facebook o Microsoft) per autenticare gli utenti. Questo argomento illustra quanto segue:

I nuovi utenti registrano l'alias di posta elettronica, che crea un account locale.

Immagine della finestra di registrazione dell'account

Selezionando il pulsante Registra viene inviato un messaggio di posta elettronica di conferma contenente un token di convalida all'indirizzo di posta elettronica.

Immagine che mostra la conferma inviata tramite posta elettronica

L'utente riceve un messaggio di posta elettronica con un token di conferma per il proprio account.

Immagine del token di conferma

Selezionando il collegamento viene confermato l'account.

Immagine che conferma l'indirizzo di posta elettronica

Ripristino/reimpostazione della password

Gli utenti locali che dimenticano la password possono avere un token di sicurezza inviato al proprio account di posta elettronica, consentendo loro di reimpostare la password.

Immagine della finestra di reimpostazione della password dimenticata

L'utente riceverà presto un messaggio di posta elettronica con un collegamento che consente di reimpostare la password.

Immagine che mostra la reimpostazione della posta elettronica della password
Selezionando il collegamento, verrà visualizzata la pagina Reimposta.

Immagine che mostra la finestra di reimpostazione della password utente

Selezionando il pulsante Reimposta si verifica che la password sia stata reimpostata.

Immagine che mostra la conferma della reimpostazione della password

Creare un'app Web ASP.NET

Per iniziare, installare ed eseguire Visual Studio 2017.

  1. Creare un nuovo progetto Web ASP.NET e selezionare il modello MVC. Web Forms supportano anche ASP.NET Identity, quindi è possibile seguire passaggi simili in un'app Web form.

  2. Modificare l'autenticazione in Account utente singoli.

  3. Eseguire l'app, selezionare il collegamento Registra e registrare un utente. A questo punto, l'unica convalida nel messaggio di posta elettronica è con l'attributo [EmailAddress].

  4. In Esplora server passare a Connessioni dati\DefaultConnection\Tables\AspNetUsers, fare clic con il pulsante destro del mouse e scegliere Apri definizione tabella.

    L'immagine seguente mostra lo AspNetUsers schema:

    Immagine che mostra lo schema A s p Net Users

  5. Fare clic con il pulsante destro del mouse sulla tabella AspNetUsers e scegliere Mostra dati tabella.

    Immagine che mostra i dati della tabella

    A questo punto il messaggio di posta elettronica non è stato confermato.

L'archivio dati predefinito per ASP.NET Identity è Entity Framework, ma è possibile configurarlo per l'uso di altri archivi dati e per aggiungere altri campi. Vedere la sezione Risorse aggiuntive alla fine di questa esercitazione.

La classe di avvio OWIN ( Startup.cs ) viene chiamata all'avvio dell'app e richiama il ConfigureAuth metodo in App_Start\Startup.Auth.cs, che configura la pipeline OWIN e inizializza ASP.NET Identity. Esaminare il metodo ConfigureAuth. Ogni CreatePerOwinContext chiamata registra un callback (salvato in OwinContext) che verrà chiamato una volta per ogni richiesta per creare un'istanza del tipo specificato. È possibile impostare un punto di interruzione nel costruttore e Create nel metodo di ogni tipo (ApplicationDbContext, ApplicationUserManager) e verificare che vengano chiamati in ogni richiesta. Un'istanza di ApplicationDbContext e ApplicationUserManager viene archiviata nel contesto OWIN, accessibile in tutta l'applicazione. ASP.NET l'identità si collega alla pipeline OWIN tramite il middleware dei cookie. Per altre informazioni, vedere Gestione della durata delle richieste per la classe UserManager in ASP.NET Identity.

Quando si modifica il profilo di sicurezza, viene generato e archiviato un nuovo timbro di sicurezza nel SecurityStamp campo della tabella AspNetUsers . Si noti che il SecurityStamp campo è diverso dal cookie di sicurezza. Il cookie di sicurezza non viene archiviato nella AspNetUsers tabella (o in qualsiasi altro punto del database Di identità). Il token del cookie di sicurezza è autofirmato usando DPAPI e viene creato con le informazioni sull'ora UserId, SecurityStamp di scadenza e .

Il middleware del cookie controlla il cookie in ogni richiesta. Il SecurityStampValidator metodo nella Startup classe raggiunge periodicamente il database e controlla periodicamente il timbro di sicurezza, come specificato con .validateInterval Ciò si verifica solo ogni 30 minuti (nell'esempio) a meno che non si modififi il profilo di sicurezza. L'intervallo di 30 minuti è stato scelto per ridurre al minimo i viaggi al database. Per altri dettagli, vedere l'esercitazione sull'autenticazione a due fattori .

In base ai commenti nel codice, il UseCookieAuthentication metodo supporta l'autenticazione dei cookie. Il SecurityStamp campo e il codice associato forniscono un ulteriore livello di sicurezza per l'app, quando si modifica la password, si verrà disconnessi dal browser con cui si è connessi. Il SecurityStampValidator.OnValidateIdentity metodo consente all'app di convalidare il token di sicurezza quando l'utente accede, che viene usato quando si modifica una password o si usa l'account di accesso esterno. Ciò è necessario per garantire che tutti i token (cookie) generati con la vecchia password vengano invalidati. Nel progetto di esempio, se si modifica la password degli utenti, viene generato un nuovo token per l'utente, tutti i token precedenti vengono invalidati e il SecurityStamp campo viene aggiornato.

Il sistema di identità consente di configurare l'app in modo che gli utenti cambino il profilo di sicurezza (ad esempio, quando l'utente modifica la password o modifica l'account di accesso associato( ad esempio da Facebook, Google, account Microsoft e così via), l'utente viene disconnesso da tutte le istanze del browser. Ad esempio, l'immagine seguente mostra l'app di esempio Single Signout , che consente all'utente di disconnettersi da tutte le istanze del browser (in questo caso, Internet Explorer, Firefox e Chrome) selezionando un pulsante. In alternativa, l'esempio consente di disconnettersi solo da un'istanza del browser specifica.

Immagine che mostra la finestra dell'app di esempio per l'accesso Single Sign-Out

L'app di esempio Single Signout mostra come ASP.NET Identity consente di rigenerare il token di sicurezza. Ciò è necessario per garantire che tutti i token (cookie) generati con la vecchia password vengano invalidati. Questa funzionalità offre un ulteriore livello di sicurezza per l'applicazione; quando si modifica la password, si verrà disconnessi in cui si è connessi all'applicazione.

Il file App_Start\IdentityConfig.cs contiene le ApplicationUserManagerclassi , EmailService e SmsService . Le EmailService classi e SmsService implementano l'interfaccia IIdentityMessageService , quindi sono disponibili metodi comuni in ogni classe per configurare posta elettronica e SMS. Anche se questa esercitazione illustra solo come aggiungere una notifica tramite SendGrid, è possibile inviare messaggi di posta elettronica usando SMTP e altri meccanismi.

La Startup classe contiene anche la piastra caldaia per aggiungere account di accesso social (Facebook, Twitter e così via), vedi la mia esercitazione MVC 5 App con Facebook, Twitter, LinkedIn e Google OAuth2 Sign-On per altre info.

Esaminare la ApplicationUserManager classe , che contiene le informazioni sull'identità degli utenti e configura le funzionalità seguenti:

  • Requisiti di complessità della password.
  • Blocco utente (tentativi e tempo).
  • Autenticazione a due fattori (2FA). In un'altra esercitazione verranno illustrati 2FA e SMS.
  • Associazione dei servizi di posta elettronica e SMS. (I'll cover SMS in another tutorial).

La ApplicationUserManager classe deriva dalla classe generica UserManager<ApplicationUser> . ApplicationUser deriva da IdentityUser. IdentityUser deriva dalla classe generica IdentityUser :

//     Default EntityFramework IUser implementation
public class IdentityUser<TKey, TLogin, TRole, TClaim> : IUser<TKey>
   where TLogin : IdentityUserLogin<TKey>
   where TRole : IdentityUserRole<TKey>
   where TClaim : IdentityUserClaim<TKey>
{
   public IdentityUser()
   {
      Claims = new List<TClaim>();
      Roles = new List<TRole>();
      Logins = new List<TLogin>();
   }

   ///     User ID (Primary Key)
   public virtual TKey Id { get; set; }

   public virtual string Email { get; set; }
   public virtual bool EmailConfirmed { get; set; }

   public virtual string PasswordHash { get; set; }

   ///     A random value that should change whenever a users credentials have changed (password changed, login removed)
   public virtual string SecurityStamp { get; set; }

   public virtual string PhoneNumber { get; set; }
   public virtual bool PhoneNumberConfirmed { get; set; }

   public virtual bool TwoFactorEnabled { get; set; }

   ///     DateTime in UTC when lockout ends, any time in the past is considered not locked out.
   public virtual DateTime? LockoutEndDateUtc { get; set; }

   public virtual bool LockoutEnabled { get; set; }

   ///     Used to record failures for the purposes of lockout
   public virtual int AccessFailedCount { get; set; }
   
   ///     Navigation property for user roles
   public virtual ICollection<TRole> Roles { get; private set; }

   ///     Navigation property for user claims
   public virtual ICollection<TClaim> Claims { get; private set; }

   ///     Navigation property for user logins
   public virtual ICollection<TLogin> Logins { get; private set; }
   
   public virtual string UserName { get; set; }
}

Le proprietà precedenti coincidono con le proprietà della AspNetUsers tabella, illustrate in precedenza.

Gli argomenti generici su IUser consentono di derivare una classe usando tipi diversi per la chiave primaria. Vedere l'esempio ChangePK che mostra come modificare la chiave primaria da stringa a int o GUID.

ApplicationUser

ApplicationUser (public class ApplicationUserManager : UserManager<ApplicationUser>) è definito in Models\IdentityModels.cs come segue:

public class ApplicationUser : IdentityUser
{
    public async Task<ClaimsIdentity> GenerateUserIdentityAsync(
        UserManager<ApplicationUser> manager)
    {
        // Note the authenticationType must match the one defined in 
       //   CookieAuthenticationOptions.AuthenticationType
        var userIdentity = await manager.CreateIdentityAsync(this, 
    DefaultAuthenticationTypes.ApplicationCookie);
        // Add custom user claims here
        return userIdentity;
    }
}

Il codice evidenziato sopra genera un claimsIdentity. ASP.NET l'identità e l'autenticazione cookie OWIN sono basate sulle attestazioni, pertanto il framework richiede che l'app generi un per ClaimsIdentity l'utente. ClaimsIdentity contiene informazioni su tutte le attestazioni per l'utente, ad esempio il nome dell'utente, l'età e i ruoli a cui appartiene l'utente. È anche possibile aggiungere altre attestazioni per l'utente in questa fase.

Il metodo OWIN AuthenticationManager.SignIn passa all'oggetto ClaimsIdentity e accede all'utente:

private async Task SignInAsync(ApplicationUser user, bool isPersistent)
{
    AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
    AuthenticationManager.SignIn(new AuthenticationProperties(){
       IsPersistent = isPersistent }, 
       await user.GenerateUserIdentityAsync(UserManager));
}

L'app MVC 5 con Facebook, Twitter, LinkedIn e Google OAuth2 Sign-On mostra come aggiungere altre proprietà alla ApplicationUser classe.

Email conferma

È consigliabile confermare il messaggio di posta elettronica di un nuovo utente registrato con per verificare che non siano rappresentazioni di un altro utente (ovvero non sono state registrate con un messaggio di posta elettronica di un altro utente). Si supponga di avere un forum di discussione, si vuole impedire "bob@example.com" la registrazione come "joe@contoso.com". Senza conferma di posta elettronica, "joe@contoso.com" potrebbe ricevere un messaggio di posta elettronica indesiderato dall'app. Si supponga che Bob abbia registrato accidentalmente come "bib@example.com" e non lo avesse notato, non sarebbe in grado di usare il ripristino della password perché l'app non ha il suo messaggio di posta elettronica corretto. Email conferma offre solo una protezione limitata dai bot e non fornisce protezione da spammer determinati, hanno molti alias di posta elettronica funzionanti che possono usare per registrare. Nell'esempio seguente l'utente non sarà in grado di modificare la password fino a quando il proprio account non è stato confermato (selezionando un collegamento di conferma ricevuto nell'account di posta elettronica registrato). È possibile applicare questo flusso di lavoro ad altri scenari, ad esempio inviando un collegamento per confermare e reimpostare la password nei nuovi account creati dall'amministratore, inviando all'utente un messaggio di posta elettronica quando hanno modificato il proprio profilo e così via. In genere si vuole impedire ai nuovi utenti di pubblicare dati nel sito Web prima che siano stati confermati tramite posta elettronica, un messaggio di testo SMS o un altro meccanismo.

Creare un esempio più completo

In questa sezione si userà NuGet per scaricare un esempio più completo con cui verrà usato.

  1. Creare un nuovo progetto Web di ASP.NET vuoto .

  2. Nella console di Gestione pacchetti immettere i comandi seguenti:

    Install-Package SendGrid
    Install-Package -Prerelease Microsoft.AspNet.Identity.Samples
    

    In questa esercitazione si userà SendGrid per inviare un messaggio di posta elettronica. Il Identity.Samples pacchetto installa il codice con cui verrà lavorato.

  3. Impostare il progetto per l'uso di SSL.

  4. Testare la creazione dell'account locale eseguendo l'app, selezionando il collegamento Registra e registrando il modulo di registrazione.

  5. Selezionare il collegamento di posta elettronica demo, che simula la conferma della posta elettronica.

  6. Rimuovere il codice di conferma del collegamento di posta elettronica demo dall'esempio (Il ViewBag.Link codice nel controller dell'account. Vedere i metodi di azione e ForgotPasswordConfirmation le visualizzazioni DisplayEmail razor .

Avviso

Se si modifica una delle impostazioni di sicurezza in questo esempio, le app di produzione dovranno eseguire un controllo di sicurezza che chiama in modo esplicito le modifiche apportate.

Esaminare il codice in App_Start\IdentityConfig.cs

L'esempio illustra come creare un account e aggiungerlo al ruolo di Amministrazione. È consigliabile sostituire il messaggio di posta elettronica nell'esempio con il messaggio di posta elettronica usato per l'account amministratore. Il modo più semplice per creare un account amministratore è a livello di codice nel Seed metodo. Si spera di avere uno strumento in futuro che consente di creare e amministrare utenti e ruoli. Il codice di esempio consente di creare e gestire utenti e ruoli, ma è prima necessario disporre di un account amministratore per eseguire i ruoli e le pagine di amministrazione utente. In questo esempio viene creato l'account amministratore quando il database viene inizializzato.

Modificare la password e modificare il nome in un account in cui è possibile ricevere notifiche tramite posta elettronica.

Avviso

Sicurezza: non archiviare mai i dati sensibili nel codice sorgente.

Come accennato in precedenza, la app.CreatePerOwinContext chiamata nella classe di avvio aggiunge callback al Create metodo del contenuto del database app, gestione utenti e classi manger di ruolo. La pipeline OWIN chiama il metodo in queste classi per ogni richiesta e archivia il Create contesto per ogni classe. Il controller dell'account espone il gestore utenti dal contesto HTTP (che contiene il contesto OWIN):

public ApplicationUserManager UserManager
{
    get
    {
        return _userManager ?? 
    HttpContext.GetOwinContext().GetUserManager<ApplicationUserManager>();
    }
    private set
    {
        _userManager = value;
    }
}

Quando un utente registra un account locale, viene chiamato il HTTP Post Register metodo:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
        var result = await UserManager.CreateAsync(user, model.Password);
        if (result.Succeeded)
        {
            var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
            var callbackUrl = Url.Action(
               "ConfirmEmail", "Account", 
               new { userId = user.Id, code = code }, 
               protocol: Request.Url.Scheme);

            await UserManager.SendEmailAsync(user.Id, 
               "Confirm your account", 
               "Please confirm your account by clicking this link: <a href=\"" 
                                               + callbackUrl + "\">link</a>");
            // ViewBag.Link = callbackUrl;   // Used only for initial demo.
            return View("DisplayEmail");
        }
        AddErrors(result);
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

Il codice precedente usa i dati del modello per creare un nuovo account utente usando il messaggio di posta elettronica e la password immessi. Se l'alias di posta elettronica si trova nell'archivio dati, la creazione dell'account ha esito negativo e il modulo viene visualizzato di nuovo. Il GenerateEmailConfirmationTokenAsync metodo crea un token di conferma sicuro e lo archivia nell'archivio dati identity ASP.NET. Il metodo Url.Action crea un collegamento contenente il UserId token di conferma e. Questo collegamento viene quindi inviato tramite posta elettronica all'utente, l'utente può selezionare il collegamento nell'app di posta elettronica per confermare il proprio account.

Configurare la conferma della posta elettronica

Passare alla pagina di iscrizione di SendGrid e registrarsi per l'account gratuito. Aggiungere codice simile al seguente per configurare SendGrid:

public class EmailService : IIdentityMessageService
{
   public Task SendAsync(IdentityMessage message)
   {
      return configSendGridasync(message);
   }

   private Task configSendGridasync(IdentityMessage message)
   {
      var myMessage = new SendGridMessage();
      myMessage.AddTo(message.Destination);
      myMessage.From = new System.Net.Mail.MailAddress(
                          "Joe@contoso.com", "Joe S.");
      myMessage.Subject = message.Subject;
      myMessage.Text = message.Body;
      myMessage.Html = message.Body;

      var credentials = new NetworkCredential(
                 ConfigurationManager.AppSettings["mailAccount"],
                 ConfigurationManager.AppSettings["mailPassword"]
                 );

      // Create a Web transport for sending email.
      var transportWeb = new Web(credentials);

      // Send the email.
      if (transportWeb != null)
      {
         return transportWeb.DeliverAsync(myMessage);
      }
      else
      {
         return Task.FromResult(0);
      }
   }
}

Nota

Email client accettano spesso solo messaggi di testo (nessun html). È necessario specificare il messaggio in testo e HTML. Nell'esempio di SendGrid precedente, questa operazione viene eseguita con il myMessage.Text codice e myMessage.Html illustrato in precedenza.

Il codice seguente illustra come inviare messaggi di posta elettronica usando la classe MailMessage in cui message.Body restituisce solo il collegamento.

void sendMail(Message message)
{
#region formatter
   string text = string.Format("Please click on this link to {0}: {1}", message.Subject, message.Body);
   string html = "Please confirm your account by clicking this link: <a href=\"" + message.Body + "\">link</a><br/>";

   html += HttpUtility.HtmlEncode(@"Or click on the copy the following link on the browser:" + message.Body);
#endregion

   MailMessage msg = new MailMessage();
   msg.From = new MailAddress("joe@contoso.com");
   msg.To.Add(new MailAddress(message.Destination));
   msg.Subject = message.Subject;
   msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(text, null, MediaTypeNames.Text.Plain));
   msg.AlternateViews.Add(AlternateView.CreateAlternateViewFromString(html, null, MediaTypeNames.Text.Html));

   SmtpClient smtpClient = new SmtpClient("smtp.gmail.com", Convert.ToInt32(587));
   System.Net.NetworkCredential credentials = new System.Net.NetworkCredential("joe@contoso.com", "XXXXXX");
   smtpClient.Credentials = credentials;
   smtpClient.EnableSsl = true;
   smtpClient.Send(msg);
}

Avviso

Sicurezza: non archiviare mai i dati sensibili nel codice sorgente. L'account e le credenziali vengono archiviati nell'appSetting. In Azure è possibile archiviare questi valori in modo sicuro nella scheda Configura nella portale di Azure. Vedere Procedure consigliate per la distribuzione di password e altri dati sensibili in ASP.NET e Azure.

Immettere le credenziali di SendGrid, eseguire l'app, registrare con un alias di posta elettronica può selezionare il collegamento conferma nel messaggio di posta elettronica. Per informazioni su come eseguire questa operazione con l'account di posta elettronica Outlook.com , vedere Configurazione SMTP C# di John Atten per Outlook.Com host SMTP e il relativo ASP.NETIdentity 2.0: Configurazione della convalida dell'account e post di autorizzazione Two-Factor.

Dopo che un utente seleziona il pulsante Registra un messaggio di posta elettronica di conferma contenente un token di convalida viene inviato all'indirizzo di posta elettronica.

Immagine della finestra di conferma inviata tramite posta elettronica

L'utente viene inviato un messaggio di posta elettronica con un token di conferma per il proprio account.

Immagine della posta elettronica ricevuta

Esaminare il codice

Nel codice seguente viene illustrato il metodo POST ForgotPassword.

public async Task<ActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = await UserManager.FindByNameAsync(model.Email);
        if (user == null || !(await UserManager.IsEmailConfirmedAsync(user.Id)))
        {
            // Don't reveal that the user does not exist or is not confirmed
            return View("ForgotPasswordConfirmation");
        }

        var code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
        var callbackUrl = Url.Action("ResetPassword", "Account", 
    new { UserId = user.Id, code = code }, protocol: Request.Url.Scheme);
        await UserManager.SendEmailAsync(user.Id, "Reset Password", 
    "Please reset your password by clicking here: <a href=\"" + callbackUrl + "\">link</a>");        
        return View("ForgotPasswordConfirmation");
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}

Il metodo ha esito negativo in modo invisibile se il messaggio di posta elettronica dell'utente non è stato confermato. Se è stato inviato un errore per un indirizzo di posta elettronica non valido, gli utenti malintenzionati potrebbero usare tali informazioni per trovare userId validi (alias di posta elettronica) da attaccare.

Il codice seguente mostra il metodo nel controller dell'account chiamato quando l'utente seleziona il ConfirmEmail collegamento di conferma nel messaggio di posta elettronica inviato:

public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
    if (userId == null || code == null)
    {
        return View("Error");
    }
    var result = await UserManager.ConfirmEmailAsync(userId, code);
    if (result.Succeeded)
    {
        return View("ConfirmEmail");
    }
    AddErrors(result);
    return View();
}

Una volta usato un token password dimenticato, viene invalidato. Il codice seguente cambia nel Create metodo (nel file App_Start\IdentityConfig.cs ) imposta i token da scadere in 3 ore.

if (dataProtectionProvider != null)
 {
    manager.UserTokenProvider =
       new DataProtectorTokenProvider<ApplicationUser>
          (dataProtectionProvider.Create("ASP.NET Identity"))
          {                    
             TokenLifespan = TimeSpan.FromHours(3)
          };
 }

Con il codice precedente, la password dimenticata e i token di conferma della posta elettronica scadono in 3 ore. Il valore predefinito TokenLifespan è un giorno.

Il codice seguente mostra il metodo di conferma della posta elettronica:

// GET: /Account/ConfirmEmail
[AllowAnonymous]
public async Task<ActionResult> ConfirmEmail(string userId, string code)
{
   if (userId == null || code == null)
   {
      return View("Error");
   }
   IdentityResult result;
   try
   {
      result = await UserManager.ConfirmEmailAsync(userId, code);
   }
   catch (InvalidOperationException ioe)
   {
      // ConfirmEmailAsync throws when the userId is not found.
      ViewBag.errorMessage = ioe.Message;
      return View("Error");
   }

   if (result.Succeeded)
   {
      return View();
   }

   // If we got this far, something failed.
   AddErrors(result);
   ViewBag.errorMessage = "ConfirmEmail failed";
   return View("Error");
}

Per rendere l'app più sicura, ASP.NET Identity supporta l'autenticazione Two-Factor (2FA). Vedere ASP.NET Identity 2.0: Configurazione della convalida dell'account e Two-Factor autorizzazione di John Atten. Anche se è possibile impostare il blocco dell'account in caso di errori di tentativi di password di accesso, questo approccio rende l'accesso soggetto ai blocchi DOS . È consigliabile usare il blocco dell'account solo con 2FA.

Risorse aggiuntive