Authentification à deux facteurs avec SMS dans ASP.NET Core

Par Rick Anderson et Swiss-Devs

Avertissement

Les applications d’authentification à deux facteurs (2FA), utilisant un algorithme de mot de passe à usage unique (TOTP) basé sur le temps, sont l’approche recommandée par le secteur pour la 2FA. La 2FA utilisant TOTP est préférée à SMS 2FA. Pour plus d’informations, consultez Activer la génération de code QR pour les applications d’authentificateur TOTP dans ASP.NET Core pour ASP.NET Core 2.0 et versions ultérieures.

Ce tutoriel montre comment configurer l’authentification à deux facteurs (2FA) à l’aide de SMS. Des instructions sont fournies pour twilio et ASPSMS, mais vous pouvez utiliser n’importe quel autre fournisseur SMS. Nous vous recommandons de suivre la confirmation de compte et la récupération de mot de passe avant de commencer ce didacticiel.

Affichez ou téléchargez l’exemple de code. Guide pratique de téléchargement.

Créer un projet ASP.NET Core

Créez une application web ASP.NET Core nommée Web2FA avec des comptes d’utilisateur individuels. Suivez les instructions fournies dans Appliquer HTTPS dans ASP.NET Core pour configurer et exiger HTTPS.

Créer un compte SMS

Créez un compte SMS, par exemple, à partir de twilio ou ASPSMS. Enregistrez les informations d’identification d’authentification (pour twilio : accountSid et authToken, pour ASPSMS : Userkey et Password).

Identification des informations d’identification du fournisseur SMS

Twilio :

Sous l’onglet Tableau de bord de votre compte Twilio, copiez le SID de compte et le jeton d’authentification.

ASPSMS :

Dans les paramètres de votre compte, accédez à Userkey et copiez-la avec votre mot de passe.

Nous allons ensuite stocker ces valeurs dans avec l’outil secret-manager dans les clés SMSAccountIdentification et SMSAccountPassword.

Spécification de SenderID/Originator

Twilio : Sous l’onglet Nombres, copiez votre numéro de téléphone Twilio.

ASPSMS : Dans le menu Déverrouiller les originateurs, déverrouillez un ou plusieurs originateurs ou choisissez un originateur alphanumérique (non pris en charge par tous les réseaux).

Nous stockerons plus tard cette valeur avec l’outil secret-manager dans la clé SMSAccountFrom.

Fournir des informations d’identification pour le service SMS

Nous allons utiliser le modèle Options pour accéder aux paramètres du compte d’utilisateur et de la clé.

  • Créez une classe pour récupérer la clé SMS sécurisée. Pour cet exemple, la classe SMSoptions est créée dans le fichier Services/SMSoptions.cs.
namespace Web2FA.Services
{
    public class SMSoptions
    {
        public string SMSAccountIdentification { get; set; }
        public string SMSAccountPassword { get; set; }
        public string SMSAccountFrom { get; set; }
    }
}

Définissez SMSAccountIdentification, SMSAccountPassword et SMSAccountFrom avec l’outil secret-manager. Par exemple :

C:/Web2FA/src/WebApp1>dotnet user-secrets set SMSAccountIdentification 12345
info: Successfully saved SMSAccountIdentification = 12345 to the secret store.
  • Ajoutez le package NuGet pour le fournisseur SMS. À partir de la console du Gestionnaire de package (PMC), exécutez :

Twilio :

Install-Package Twilio

ASPSMS :

Install-Package ASPSMS

  • Ajoutez du code dans le Services/MessageServices.cs fichier pour activer SMS. Utilisez la section Twilio ou 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);
        }
    }
}

Configurer le démarrage pour utiliser SMSoptions

Ajoutez SMSoptions au conteneur de service dans la méthode ConfigureServices dans le Startup.cs :

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

Activer l’authentification à deux facteurs

Ouvrez le Views/Manage/Index.cshtmlRazor fichier d’affichage et supprimez les caractères de commentaire (afin qu’aucun balisage ne soit commenté).

Se connecter avec l’authentification à deux facteurs

  • Exécutez l’application et inscrivez un nouvel utilisateur

Web application Register view open in Microsoft Edge

  • Appuyez sur votre nom d’utilisateur, ce qui active la méthode d’action Index dans Gérer le contrôleur. Appuyez ensuite sur le lien Ajouter de numéro de téléphone.

Manage view - tap the

  • Ajoutez un numéro de téléphone qui recevra le code de vérification, puis appuyez sur Envoyer le code de vérification.

Add Phone Number page

  • Vous recevrez un sms avec le code de vérification. Entrez-le, puis appuyez sur Envoyer

Verify Phone Number page

Si vous ne recevez pas de sms, consultez la page de journal twilio.

  • La vue Gérer indique que votre numéro de téléphone a été ajouté avec succès.

Manage view - phone number added successfully

  • Appuyez sur Activer pour activer l’authentification à deux facteurs.

Manage view - enable two-factor authentication

Test Authentification à 2 facteurs

  • Fermez la session.

  • Connectez-vous.

  • Le compte d’utilisateur ayant activé l’authentification à deux facteurs, vous devez fournir le deuxième facteur d’authentification. Dans ce tutoriel, vous avez activé la vérification par téléphone. Les modèles intégrés vous permettent également de configurer l’e-mail en tant que deuxième facteur. Vous pouvez configurer des deuxièmes facteurs supplémentaires pour l’authentification, tels que des codes QR. Appuyez sur Envoyer.

Send Verification Code view

  • Entrez le code que vous obtenez dans le message SMS.

  • Si vous cliquez sur la case Mémoriser ce navigateur , vous n’avez pas besoin d’utiliser l’authentification 2FA pour vous connecter lorsque vous utilisez le même appareil et le même navigateur. L’activation de la 2FA et le fait de cliquer sur Mémoriser ce navigateur vous offre une protection 2FA renforcée contre les utilisateurs malveillants qui tentent d’accéder à votre compte, tant qu’ils n’ont pas accès à votre appareil. Vous pouvez le faire sur n’importe quel appareil privé que vous utilisez régulièrement. En définissant Mémoriser ce navigateur, vous bénéficiez de la sécurité supplémentaire de l’authentification par 2fa à partir d’appareils que vous n’utilisez pas régulièrement, et vous obtenez la commodité de ne pas avoir à passer par 2fa sur vos propres appareils.

Verify view

Verrouillage de compte pour la protection contre les attaques par force brute

Le verrouillage de compte est recommandé avec 2fa. Une fois qu’un utilisateur se connecte via un compte local ou social, chaque tentative ayant échoué à 2fa est stockée. Si le nombre maximal de tentatives d’accès ayant échoué est atteint, l’utilisateur est verrouillé (par défaut : verrouillage de 5 minutes après 5 tentatives d’accès ayant échoué). Une authentification réussie réinitialise le nombre de tentatives d’accès ayant échoué et réinitialise l’horloge. Le nombre maximal de tentatives d’accès ayant échoué et le temps de verrouillage peuvent être définis avec MaxFailedAccessAttempts et DefaultLockoutTimeSpan. Le code suivant configure le verrouillage du compte pendant 10 minutes après 10 tentatives d’accès ayant échoué :

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);
}

Confirmez que PasswordSignInAsync définit lockoutOnFailure sur true :

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