Les applications modernes s'éloignent de plus en plus des mots de passe traditionnels et se tournent vers des méthodes d'authentification sans mot de passe qui sont à la fois plus sécurisées et plus simples pour les utilisateurs. Dans cet article, je vais montrer comment authentifier les utilisateurs dans une application ASP.NET Core à l'aide de FoxIDs avec OpenID Connect et activer une expérience de connexion entièrement sans mot de passe à l'aide de codes à usage unique envoyés par e-mail.

Nous allons partir d'un environnement FoxIDs propre, créer une nouvelle application Web ASP.NET Core, la connecter à OpenID Connect et enfin activer la connexion à passwordless avec OTP par courrier électronique.

Création d'un environnement de développement FoxIDs

J'ai commencé par créer un nouvel environnement de développement vide dans FoxIDs. Un environnement propre simplifie la configuration de l'authentification à partir de zéro et garantit que vous pouvez reproduire ces étapes dans votre propre tenant.

Environnement FoxIDs vide

Si vous n'avez jamais utilisé FoxIDs auparavant, vous pouvez créer un tenant gratuit sur :

https://www.foxids.com

Chaque tenant est livré avec deux environnements prêts à l'emploi pour que vous puissiez expérimenter librement.

Configurer l'authentification

Commencez par configurer la façon dont les utilisateurs doivent se connecter. Dans ce cas, nous souhaitons que les utilisateurs se connectent sans mot de passe, en utilisant uniquement leur adresse e-mail et un mot de passe à usage unique (OTP) qui leur a été envoyé.

  1. Sélectionnez l'onglet Authentifications dans votre environnement FoxIDs.
  2. Cliquez sur Par défaut — Interface utilisateur de connexion utilisateur.
  3. Dans la section Authentification, désactivez Authentification par mot de passe et activez Sans mot de passe avec e-mail (mot de passe à usage unique).
  4. Cliquez sur Mettre à jour pour enregistrer les modifications.
Configurer la méthode de connexion par authentification

Cela permet aux utilisateurs de créer un nouveau compte et offre une expérience sans mot de passe où ils s'authentifient simplement en entrant leur adresse e-mail et le OTP qu'ils reçoivent.

Création de l'application ASP.NET Core

Ensuite, nous avons besoin d'une application pour nous authentifier. Vous pouvez utiliser Visual Studio ou VS Code, tout ce qui prend en charge le développement standard ASP.NET Core.

Lisez le message « Authentification sans mot de passe dans une application ASP.NET Core générée par l'IA avec FoxIDs et OTP par courrier électronique » si vous souhaitez générer l'application ASP.NET Core avec une invite AI.

Pour cette procédure pas à pas, je crée une simple application ASP.NET Core Razor Pages ciblant .NET 10 dans Visual Studio, mais la même approche fonctionne pour MVC, une application Web Blazor ou tout autre projet ASP.NET Core.

Créer l'application ASP.NET par défaut

Exécutez l'application ; l'exemple d'application s'exécute localement sur https://localhost:7283/

Exécuter l'application ASP.NET par défaut

Vous pouvez trouver l'exemple de code dans : https://github.com/ITfoxtec/dotnet.samples/tree/main/WebAppPasswordLessEmail

Configurer l'application Web dans FoxIDs

Maintenant que nous connaissons l'adresse locale de l'application Web, nous pouvons l'enregistrer dans FoxIDs afin qu'elle puisse authentifier les utilisateurs via OpenID Connect.

  1. Sélectionnez l'onglet Applications dans votre environnement FoxIDs.
  2. Choisissez Nouvelle application, puis sélectionnez Application Web — OpenID Connect.
  3. Dans Nom, saisissez un nom, par exemple : Application Web ASP.NET.
  4. Dans URI de redirection, ajoutez l'adresse de base de l'application : https://localhost:7283/ Par défaut, FoxIDs permet la redirection vers n'importe quelle page suivante sous cette URL de base. Si vous préférez une validation plus stricte, vous pouvez exiger des URI de redirection absolus.
  5. Cliquez sur Créer.
Ajouter une application dans FoxIDs

FoxIDs affiche désormais les détails de connexion de votre nouvelle application, notamment :

  • Authority
  • Identifiant client
  • ** Secret client **
Application créée dans FoxIDs

Copiez le Authority et le Client ID dans la section IdentitySettings du projet. Stockez le Client Secret dans les secrets utilisateur .NET localement ou dans une variable d'environnement sécurisée ou un magasin de secrets en production.

Configurer l'authentification dans l'application ASP.NET

Une fois l'application FoxIDs créée, l'étape suivante consiste à configurer l'authentification dans le projet ASP.NET Core. Nous utiliserons l'authentification par cookie pour la session locale et OpenID Connect pour communiquer avec FoxIDs.

Ouvrez Program.cs et ajoutez la configuration d'authentification avec (builder.Services.AddAuthentication... et app.UseAuthentication() 😉 :

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Logging;

var builder = WebApplication.CreateBuilder(args);

// Detailed authentication errors can help locally, but must not be enabled in production.
if (builder.Environment.IsDevelopment())
{
    IdentityModelEventSource.ShowPII = true;
}

// Add authentication with cookie and OpenID Connect
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options =>
    {
        options.Authority = builder.Configuration["IdentitySettings:Authority"];
        options.ClientId = builder.Configuration["IdentitySettings:ClientId"];
        options.ClientSecret = builder.Configuration["IdentitySettings:ClientSecret"];
        options.ResponseType = OpenIdConnectResponseType.Code;
        options.SaveTokens = true;

        options.Scope.Add("email");
        options.Scope.Add("profile");
        options.Scope.Add("offline_access");

        options.MapInboundClaims = false;
        options.TokenValidationParameters.NameClaimType = "sub";
        options.TokenValidationParameters.RoleClaimType = "role";

        options.Events = new OpenIdConnectEvents
        {
            OnTokenValidated = async context =>
            {
                // Custom claims transformation or other logic can be added here.
                await Task.CompletedTask;
            },
            OnAuthenticationFailed = context =>
            {
                if (!builder.Environment.IsDevelopment())
                {
                    return Task.CompletedTask;
                }

                context.HandleResponse();
                context.Response.StatusCode = 500;
                context.Response.ContentType = "text/plain";
                return context.Response.WriteAsync(context.Exception.ToString());
            }
        };
    });

// Add services to the container.
builder.Services.AddRazorPages();
builder.Services.AddControllers();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    // The default HSTS value is 30 days.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapStaticAssets();
app.MapControllers();
app.MapRazorPages()
   .WithStaticAssets();

app.Run();

Ajoutez les détails de connexion non secrets FoxIDs à appsettings.json. Gardez le secret client hors du contrôle de code source et chargez-le à partir des secrets utilisateur .NET pendant le développement local ou à partir d'une variable d'environnement sécurisée ou d'un magasin de secrets en production.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "AllowedHosts": "*",
  "IdentitySettings": {
    "Authority": "https://foxids.com/{tenant}/{environment}/{application}/",
    "ClientId": "your-client-id"
  }
}

Stockez le secret client localement sans l'écrire dans appsettings.json :

dotnet user-secrets init
dotnet user-secrets set "IdentitySettings:ClientSecret" "your-client-secret"

Remplacez les exemples de valeurs par Authority, l'ID client et le secret client de votre propre environnement FoxIDs. Ne commettez jamais le vrai secret.

Afficher les claims sur la page principale

Pour les besoins de cet exemple, affichez les claims sur la page principale. Ouvrez Index.cshtml et modifiez le contenu :

@page
@model IndexModel
@{
    ViewData["Title"] = "Home page";
}

@if (User.Identity?.IsAuthenticated == true)
{
    <h2 class="mt-4">Claims</h2>
    <table class="table table-striped table-bordered">
        <thead>
            <tr>
                <th>Type</th>
                <th>Value</th>
            </tr>
        </thead>
        <tbody>
        @foreach (var claim in User.Claims)
        {
            <tr>
                <td>@claim.Type</td>
                <td>@claim.Value</td>
            </tr>
        }
        </tbody>
    </table>
}
else
{
    <p class="mt-4 text-muted">Not signed in.</p>
}

Ajouter un menu de connexion à l'application

Pour permettre aux utilisateurs de se connecter, nous ajoutons une vue partielle pour les contrôles de connexion et de déconnexion.

Créez un nouveau fichier 😛ages/Shared/_LoginPartial.cshtml avec le contenu :

@if (User.Identity?.IsAuthenticated == true)
{
    <ul class="navbar-nav">
        <li class="nav-item">
            <form class="form-inline" asp-controller="Auth" asp-action="Logout" method="post">
                @Html.AntiForgeryToken()
                <button type="submit" class="nav-link btn btn-link text-dark">Log off</button>
            </form>
        </li>
    </ul>
}
else
{
    <ul class="navbar-nav navbar-right">
        <li class="nav-item">
            <a class="nav-link text-dark" asp-controller="Auth" asp-action="Login">Log in</a>
        </li>
    </ul>
}

Incluez ensuite la connexion partielle dans le menu de navigation. Dans Pages/Shared/_Layout.cshtml, ajoutez l'élément de connexion partielle à la fin de la barre de navigation :

<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
    <ul class="navbar-nav flex-grow-1">
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
        </li>
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
        </li>
    </ul>
    <partial name="_LoginPartial" />
</div>

Ajoutez ensuite une page de destination pour les demandes de connexion et de déconnexion. Créez un dossier Contrôleurs et créez un nouveau fichier de contrôleur dans le dossier : Controllers/AuthController.cs avec le contenu :

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace WebAppPasswordLessEmail.Controllers
{
    [AllowAnonymous]
    [Route("[controller]/[action]")]
    public class AuthController : Controller
    {
        [HttpGet]
        public IActionResult Login()
        {
            var redirectUri = Url.Content("~/");
            if (User.Identity?.IsAuthenticated == true)
            {
                return LocalRedirect(redirectUri);
            }

            return Challenge(new AuthenticationProperties { RedirectUri = redirectUri },
                OpenIdConnectDefaults.AuthenticationScheme);
        }

        [HttpPost]
        [ValidateAntiForgeryToken]
        public IActionResult Logout()
        {
            var redirectUri = Url.Content("~/");
            if (User.Identity?.IsAuthenticated != true)
            {
                return LocalRedirect(redirectUri);
            }

            return SignOut(new AuthenticationProperties { RedirectUri = redirectUri },
                CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme);
        }
    }
}

Exécutez et rechargez l'application et vous verrez maintenant une option Connexion dans le menu supérieur.

Exemple d'application

Se connecter

Cliquez sur Connexion et vous êtes redirigé vers l'écran de connexion FoxIDs.

Sélectionnez Créer un utilisateur.

Écran de connexion FoxIDs

Remplissez le formulaire Créer un utilisateur avec votre adresse e-mail (ou une adresse e-mail test à laquelle vous avez accès), votre prénom et votre nom de famille, puis cliquez sur Créer.

Créer un utilisateur test

Saisissez le mot de passe à usage unique (OTP) que vous avez reçu par e-mail, puis cliquez sur Connexion.

Connectez-vous avec un mot de passe à usage unique (OTP)

Vous êtes connecté et les claims de votre utilisateur test s’affichent.

Connecté, afficher les claims

Ensuite, essayez de vous déconnecter et de vous reconnecter pour bénéficier du flux de connexion sans mot de passe en utilisant l'e-mail OTP.