Zwei-Faktor-Authentifizierung per SMS in ASP.NET Core

Von Rick Anderson und Swiss-Devs

Warnung

Authenticator-Apps mit Zwei-Faktor-Authentifizierung (Two Factor Authentication, 2FA), die einen Algorithmus für ein zeitbasiertes Einmalkennwort (Time-based One-time Password Algorithm, TOTP) verwenden, sind der branchenweit empfohlene Ansatz für 2FA. 2FA mit TOTP wird gegenüber SMS-2FA bevorzugt. Weitere Informationen finden Sie unter Aktivieren der QR-Code-Generierung für TOTP-Authentifikator-Apps in ASP.NET Core für ASP.NET Core 2.0 und höher.

In diesem Tutorial erfahren Sie, wie Sie die Zwei-Faktor-Authentifizierung (2FA) über SMS einrichten. Es werden Anweisungen für Twilio und ASPSMS angegeben, aber Sie können auch jeden anderen SMS-Anbieter verwenden. Es wird empfohlen, Kontobestätigung und Kennwortwiederherstellung abzuschließen, bevor Sie mit diesem Tutorial beginnen.

Anzeigen oder Herunterladen von Beispielcode Informationen zum Herunterladen.

Erstellen eines neuen ASP.NET Core-Projekts

Erstellen Sie eine neue ASP.NET Core-Web-App namens Web2FA mit einzelnen Benutzerkonten. Befolgen Sie die Anweisungen unter Erzwingen von HTTPS in ASP.NET Core, um HTTPS einzurichten und anzufordern.

Erstellen eines SMS-Kontos

Erstellen Sie ein SMS-Konto, z. B. über Twilio oder ASPSMS. Notieren Sie die Anmeldeinformationen für die Authentifizierung (für Twilio: „accountSid“ und „authToken“, für ASPSMS: „Userkey“ und „Password“).

Ermitteln der Anmeldeinformationen des SMS-Anbieters

Twilio:

Kopieren Sie auf der Registerkarte „Dashboard“ Ihres Twilio-Kontos die Konto-SID und das Authentifizierungstoken.

ASPSMS:

Navigieren Sie in Ihren Kontoeinstellungen zu Userkey, und kopieren Sie diesen Wert zusammen mit dem in Password angegebenen Kennwort.

Diese Werte werden später mit dem Secret-Manager-Tool in den Schlüsseln SMSAccountIdentification und SMSAccountPassword gespeichert.

Angeben von SenderID/Originator

Twilio: Kopieren Sie auf der Registerkarte mit Nummern Ihre Twilio-Telefonnummer.

ASPSMS: Entsperren Sie im Menü „Unlock Originators“ (Absender entsperren) mindestens einen oder Absender, oder wählen Sie einen alphanumerischen Absender aus (wird nicht von allen Netzwerken unterstützt).

Dieser Wert wird später mit dem Secret-Manager-Tool im Schlüssel SMSAccountFrom gespeichert.

Bereitstellen von Anmeldeinformationen für den SMS-Dienst

Wir verwenden das Optionsmuster, um auf die Benutzerkonto- und Schlüsseleinstellungen zuzugreifen.

  • Erstellen Sie eine Klasse, um den sicheren SMS-Schlüssel abzurufen. Für dieses Beispiel wird die SMSoptions-Klasse in der Datei Services/SMSoptions.cs erstellt.
namespace Web2FA.Services
{
    public class SMSoptions
    {
        public string SMSAccountIdentification { get; set; }
        public string SMSAccountPassword { get; set; }
        public string SMSAccountFrom { get; set; }
    }
}

Legen Sie SMSAccountIdentification, SMSAccountPassword und SMSAccountFrom mit dem Secret-Manager-Tool fest. Beispiel:

C:/Web2FA/src/WebApp1>dotnet user-secrets set SMSAccountIdentification 12345
info: Successfully saved SMSAccountIdentification = 12345 to the secret store.
  • Fügen Sie das NuGet-Paket für den SMS-Anbieter hinzu. Führen Sie an der Paket-Manager-Konsole (PMC) Folgendes aus:

Twilio:

Install-Package Twilio

ASPSMS:

Install-Package ASPSMS

  • Fügen Sie der Datei Services/MessageServices.cs Code hinzu, um SMS zu aktivieren. Verwenden Sie entweder den Abschnitt für Twilio oder den für ASPSMS:

Twilio:

using Microsoft.Extensions.Options;
using System.Threading.Tasks;
using Twilio;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;

namespace Web2FA.Services
{
    // This class is used by the application to send Email and SMS
    // when you turn on two-factor authentication in ASP.NET Identity.
    // For more details see this link https://go.microsoft.com/fwlink/?LinkID=532713
    public class AuthMessageSender : IEmailSender, ISmsSender
    {
        public AuthMessageSender(IOptions<SMSoptions> optionsAccessor)
        {
            Options = optionsAccessor.Value;
        }

        public SMSoptions Options { get; }  // set only via Secret Manager

        public Task SendEmailAsync(string email, string subject, string message)
        {
            // Plug in your email service here to send an email.
            return Task.FromResult(0);
        }

        public Task SendSmsAsync(string number, string message)
        {
            // Plug in your SMS service here to send a text message.
            // Your Account SID from twilio.com/console
            var accountSid = Options.SMSAccountIdentification;
            // Your Auth Token from twilio.com/console
            var authToken = Options.SMSAccountPassword;

            TwilioClient.Init(accountSid, authToken);

            return MessageResource.CreateAsync(
              to: new PhoneNumber(number),
              from: new PhoneNumber(Options.SMSAccountFrom),
              body: message);
        }
    }
}

ASPSMS:

using Microsoft.Extensions.Options;
using System.Threading.Tasks;

namespace Web2FA.Services
{
    // This class is used by the application to send Email and SMS
    // when you turn on two-factor authentication in ASP.NET Identity.
    // For more details see this link https://go.microsoft.com/fwlink/?LinkID=532713
    public class AuthMessageSender : IEmailSender, ISmsSender
    {
        public AuthMessageSender(IOptions<SMSoptions> optionsAccessor)
        {
            Options = optionsAccessor.Value;
        }

        public SMSoptions Options { get; }  // set only via Secret Manager

        public Task SendEmailAsync(string email, string subject, string message)
        {
            // Plug in your email service here to send an email.
            return Task.FromResult(0);
        }

        public Task SendSmsAsync(string number, string message)
        {
            ASPSMS.SMS SMSSender = new ASPSMS.SMS();

            SMSSender.Userkey = Options.SMSAccountIdentification;
            SMSSender.Password = Options.SMSAccountPassword;
            SMSSender.Originator = Options.SMSAccountFrom;

            SMSSender.AddRecipient(number);
            SMSSender.MessageData = message;

            SMSSender.SendTextSMS();

            return Task.FromResult(0);
        }
    }
}

Konfigurieren des Startvorgangs für SMSoptions

Fügen Sie SMSoptions über die ConfigureServices-Methode in Startup.cs dem Dienstcontainer hinzu:

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
    services.Configure<SMSoptions>(Configuration);
}

Zweistufige Authentifizierung aktivieren

Öffnen Sie die Razor-Ansichtsdatei Views/Manage/Index.cshtml, und entfernen Sie die Kommentarzeichen (damit kein Markup auskommentiert wird).

Anmelden über die Zwei-Faktor-Authentifizierung

  • Ausführen der App und Registrieren neuer Benutzer*innen

Web application Register view open in Microsoft Edge

  • Tippen Sie auf Ihren Benutzernamen, wodurch die Index-Aktionsmethode unter „Controller verwalten“ aktiviert wird. Tippen Sie dann für die Telefonnummer auf den Link Hinzufügen.

Manage view - tap the

  • Fügen Sie eine Telefonnummer hinzu, die den Überprüfungscode empfangen soll, und tippen Sie auf Prüfcode senden.

Add Phone Number page

  • Sie erhalten eine SMS mit dem Prüfcode. Geben Sie ihn ein, und tippen Sie auf Senden.

Verify Phone Number page

Wenn Sie keine SMS erhalten, prüfen Sie die Twilio-Protokollseite.

  • Die Verwaltungsansicht zeigt, dass Ihre Telefonnummer erfolgreich hinzugefügt wurde.

Manage view - phone number added successfully

  • Tippen Sie auf Aktivieren, um die Zwei-Faktor-Authentifizierung zu aktivieren.

Manage view - enable two-factor authentication

Testen der Zwei-Faktor-Authentifizierung

  • Melden Sie sich ab.

  • Melden Sie sich an.

  • Für das Benutzerkonto wurde die Zwei-Faktor-Authentifizierung aktiviert, sodass Sie den zweiten Authentifizierungsfaktor angeben müssen. In diesem Tutorial haben Sie die Telefonverifizierung aktiviert. Mit den integrierten Vorlagen können Sie auch E-Mail als zweiten Faktor einrichten. Sie können zusätzliche zweite Faktoren für die Authentifizierung einrichten, z. B. QR-Codes. Tippen Sie auf Senden.

Send Verification Code view

  • Geben Sie den Code ein, den Sie in der SMS-Nachricht erhalten.

  • Wenn Sie auf das Kontrollkästchen Diesen Browser merken klicken, ist 2FA nicht zum Anmelden erforderlich, solange Sie dasselbe Gerät und denselben Browser verwenden. Wenn Sie 2FA aktivieren und auf Diesen Browser merken klicken, erhalten Sie einen starken 2FA-Schutz vor den Zugriffsversuchen böswilliger Benutzer*innen auf Ihr Konto, solange diese keinen Zugang zu Ihrem Gerät haben. Sie können diese Einstellung auf jedem privaten Gerät vornehmen, das Sie regelmäßig verwenden. Die Einstellung Diesen Browser merken bietet Ihnen die zusätzliche Sicherheit von 2FA auf Geräten, die Sie nicht regelmäßig verwenden, und den Komfort, 2FA auf Ihren eigenen Geräten nicht durchlaufen zu müssen.

Verify view

Kontosperrung zum Schutz vor Brute-Force-Angriffen

Die Kontosperrung wird bei 2FA empfohlen. Sobald sich ein/eine Benutzer*in über ein lokales Konto oder ein Konto bei sozialen Netzwerken anmeldet, wird jeder fehlerhafte 2FA-Versuch gespeichert. Wenn die maximale Anzahl fehlerhafter Zugriffsversuche erreicht ist, wird der/die Benutzer*in gesperrt (standardmäßig 5 Minuten nach 5 fehlerhaften Zugriffsversuchen). Bei einer erfolgreichen Authentifizierung werden die Anzahl der fehlerhaften Zugriffsversuche und die Uhr zurückgesetzt. Die maximale Anzahl fehlerhafter Zugriffsversuche und die Sperrzeit können mit MaxFailedAccessAttempts und DefaultLockoutTimeSpan festgelegt werden. Im Folgenden wird die Kontosperrung auf 10 Minuten nach 10 fehlerhaften Zugriffsversuchen konfiguriert:

public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    services.AddMvc();

    services.Configure<IdentityOptions>(options =>
    {
        options.Lockout.MaxFailedAccessAttempts = 10;
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
    });

    // Add application services.
    services.AddTransient<IEmailSender, AuthMessageSender>();
    services.AddTransient<ISmsSender, AuthMessageSender>();
    services.Configure<SMSoptions>(Configuration);
}

Vergewissern Sie sich, dass lockoutOnFailure von PasswordSignInAsync auf true festgelegt wird:

var result = await _signInManager.PasswordSignInAsync(
                 Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);