Présentation de Identity sur ASP.NET Core

ASP.NET Core Identity :

  • Est une API qui prend en charge la fonctionnalité de connexion par interface utilisateur.
  • Gère les utilisateurs, les mots de passe, les données de profil, les rôles, les revendications, les jetons, la confirmation par e-mail, etc.

Les utilisateurs peuvent créer un compte avec les informations de connexion stockées dans Identity ou utiliser un fournisseur de connexion externe. Les fournisseurs de connexion externes pris en charge incluent Facebook, Google, Compte Microsoft et Twitter.

Pour plus d’informations sur la façon d’exiger l’authentification pour tous les utilisateurs de l’application, consultez Créer une application ASP.NET Core avec des données utilisateur protégées par autorisation.

Le code source Identity est disponible sur GitHub. Générez l’ossature Identity et affichez les fichiers générés pour examiner comment le modèle interagit avec Identity.

Identity est généralement configuré à l’aide d’une base de données SQL Server pour stocker les noms d’utilisateur, les mots de passe et les données de profil. Vous pouvez également utiliser un autre magasin persistant, par exemple Azure Table Storage.

Dans cette rubrique, vous allez apprendre à utiliser Identity pour inscrire, connecter et déconnecter un utilisateur. Remarque : les modèles traitent le nom d’utilisateur et l’adresse e-mail comme étant identiques pour les utilisateurs. Pour obtenir des instructions plus détaillées sur la création d’applications qui utilisent Identity, consultez la section Étapes suivantes.

Pour plus d’informations sur Identity dans les applications Blazor, consultez ASP.NET Core Blazor authentification et autorisation et les articles qui le suivent dans la documentation Blazor.

ASP.NET Core Identity n'est pas lié à la plateforme d'identités Microsoft. La plateforme d’identités Microsoft est la suivante :

  • Évolution de la plateforme de développement Azure Active Directory (Azure AD).
  • Solution d’identité alternative pour l’authentification et l’autorisation dans ASP.NET Core applications.

ASP.NET Core Identity ajoute la fonctionnalité de connexion de l’interface utilisateur aux applications web ASP.NET Core. Pour sécuriser les API web et SPA, utilisez l’une des options suivantes :

Duende Identity Server est une infrastructure OpenID Connect et OAuth 2.0 pour ASP.NET Core. Duende Identity Server active les fonctionnalités de sécurité suivantes :

  • Authentification en tant que service (AaaS)
  • Authentification/déconnexion unique (SSO) sur plusieurs types d’applications
  • Contrôle d'accès pour les API
  • Passerelle de fédération

Important

Duende Software peut vous demander de payer des frais de licence pour une utilisation en production de Duende Identity Server. Pour plus d’informations, consultez Migrate de ASP.NET Core dans .NET 5 à .NET 6.

Pour plus d’informations, consultez la documentation Duende Identity Server (site web de Duende Software).

Consultez ou téléchargez l’exemple de code (comment télécharger).

Créer un Blazor Web App avec authentification

Créez un ASP.NET Core Blazor Web App project avec des comptes individuels.

Note

Pour une Razor expérience Pages, consultez la section Créer une Razor application Pages avec authentification .

Pour une expérience MVC, consultez la section Créer une application MVC avec authentification .

  • Sélectionnez le Blazor Web App modèle. Cliquez sur Suivant.
  • Effectuez les sélections suivantes :
    • Type d’authentification : Comptes individuels
    • Mode de rendu interactif : Serveur
    • Emplacement d’interactivité : Global
  • Cliquez sur Créer.

Le project généré inclut les composants IdentityRazor. Les composants se trouvent dans le dossier Components/Account du serveur project. Par exemple:

  • Components/Account/Pages/Register.razor
  • Components/Account/Pages/Login.razor
  • Components/Account/Pages/Manage/ChangePassword.razor

Identity Razor les composants sont décrits individuellement dans la documentation pour des cas d’usage spécifiques et sont susceptibles de modifier chaque version. Lorsque vous générez un Blazor Web App avec des comptes individuels, IdentityRazor composants sont inclus dans le projet généré. Les composants IdentityRazor peuvent également être inspectés dans le dossier Components/Account du projet de serveur dans le modèle de projet Blazor Web App (référentiel GitHub dotnet/aspnetcore).

Note

Les liens de documentation vers .NET source de référence chargent généralement la branche par défaut du référentiel, qui représente le développement actuel pour la prochaine version de .NET. Pour sélectionner une balise pour une version spécifique, utilisez la liste déroulante Échanger les branches ou les balises. Pour plus d’informations, consultez Comment choisir une étiquette de version du code source d'ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Pour plus d’informations, consultez ASP.NET Core Blazor authentification et autorisation et les articles qui le suivent dans la documentation Blazor. La plupart des articles de la zone Security et Identity de l’ensemble de documentation principal ASP.NET Core s’appliquent aux applications Blazor. Toutefois, le Blazor jeu de documentation contient des articles et des conseils qui remplacent ou ajoutent des informations. Nous vous recommandons d’étudier d’abord l’ensemble de documentation général d'ASP.NET Core, puis d’ensuite accéder aux articles des documentations BlazorSecurity et Identity autres documentation.

Créer une Razor application Pages avec authentification

Créez une application web ASP.NET Core (Razor Pages) project avec des comptes individuels.

  • Sélectionnez le modèle ASP.NET Core Web App (Razor Pages). Cliquez sur Suivant.
  • Pour le type d’authentification, sélectionnez Comptes individuels.
  • Cliquez sur Créer.

Le projet généré fournit ASP.NET Core Identity en tant que bibliothèque de classes Razor(RCL). La bibliothèque de classes IdentityRazor expose les points de terminaison avec la zone Identity. Par exemple:

  • Areas/Identity/Pages/Account/Register
  • Areas/Identity/Pages/Account/Login
  • Areas/Identity/Pages/Account/Manage/ChangePassword

Les pages sont décrites individuellement dans la documentation pour des cas d’usage spécifiques et sont susceptibles de modifier chaque version. Pour afficher toutes les pages du RCL, consultez la source de référence ASP.NET Core (référentiel dotnet/aspnetcore GitHub, Identity/UI/src/Areas/Identity/Pages dossier). Vous pouvez générer une structure de pages individuelles ou toutes les pages dans l’application. Pour plus d’informations, consultez Scaffold Identity dans les projets ASP.NET Core.

Créer une application MVC avec authentification

Créez un ASP.NET Core MVC project avec des comptes individuels.

  • Sélectionnez le modèle ASP.NET Core Web App (modèle-View-Controller). Cliquez sur Suivant.
  • Pour le type d’authentification, sélectionnez Comptes individuels.
  • Cliquez sur Créer.

Le projet généré fournit ASP.NET Core Identity en tant que bibliothèque de classes Razor(RCL). La bibliothèque de classes IdentityRazor est basée sur Razor Pages et expose des points de terminaison avec la zone Identity. Par exemple:

  • Areas/Identity/Pages/Account/Register
  • Areas/Identity/Pages/Account/Login
  • Areas/Identity/Pages/Account/Manage/ChangePassword

Les pages sont décrites individuellement dans la documentation pour des cas d’usage spécifiques et sont susceptibles de modifier chaque version. Pour afficher toutes les pages du RCL, consultez la source de référence ASP.NET Core (référentiel dotnet/aspnetcore GitHub, Identity/UI/src/Areas/Identity/Pages dossier). Vous pouvez générer une structure de pages individuelles ou toutes les pages dans l’application. Pour plus d’informations, consultez Scaffold Identity dans les projets ASP.NET Core.

Appliquer des migrations

Appliquez les migrations pour initialiser la base de données.

Exécutez la commande suivante dans la console Gestionnaire de package (PMC) :

Update-Database

Tester l’inscription et la connexion

Exécutez l’application et inscrivez un utilisateur. Selon la taille de votre écran, vous devrez peut-être sélectionner le bouton bascule de navigation pour afficher les liens d’inscription et de connexion.

Afficher la base de données Identity

  • Dans le menu View, sélectionnez SQL Server Explorateur d'objets (SSOX).
  • Accédez à (localdb)MSSQLLocalDB(SQL Server 13). Cliquez avec le bouton droit sur dbo.AspNetUsers>Afficher les données :

Menu contextuel de la table AspNetUsers dans SQL Server Explorateur d'objets

Configurer les services Identity

Les services sont ajoutés dans Program.cs. Le modèle classique consiste à appeler les méthodes dans l’ordre suivant :

  1. Add{Service}
  2. builder.Services.Configure{Service}
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebApp1.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

builder.Services.Configure<IdentityOptions>(options =>
{
    // Password settings.
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
    options.Password.RequiredUniqueChars = 1;

    // Lockout settings.
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.AllowedForNewUsers = true;

    // User settings.
    options.User.AllowedUserNameCharacters =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
    options.User.RequireUniqueEmail = false;
});

builder.Services.ConfigureApplicationCookie(options =>
{
    // Cookie settings
    options.Cookie.HttpOnly = true;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

    options.LoginPath = "/Identity/Account/Login";
    options.AccessDeniedPath = "/Identity/Account/AccessDenied";
    options.SlidingExpiration = true;
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

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

app.MapRazorPages();

app.Run();

Le code précédent configure Identity avec les valeurs d’option par défaut. Les services sont accessibles à l’application au moyen de l’injection de dépendances.

Identity est activé en appelant UseAuthentication. UseAuthentication ajoute un intergiciel d’authentification au pipeline de requêtes.

L’application générée par un modèle n’utilise pas l’autorisation. app.UseAuthorization est inclus pour s’assurer qu’il est ajouté dans l’ordre correct si l’application ajoute une autorisation. UseRouting, UseAuthentication et UseAuthorization doivent être appelés dans l’ordre indiqué dans le code précédent.

Pour plus d’informations sur IdentityOptions, consultez les articles IdentityOptions et Démarrage d’une application.

Métriques ASP.NET Core Identity

les métriques ASP.NET Core Identity fournissent des fonctionnalités de surveillance pour les processus de gestion et d’authentification des utilisateurs. Ces métriques vous aident à détecter des modèles de connexion inhabituels qui peuvent indiquer des menaces de sécurité, suivre les performances des opérations d’identité et comprendre comment les utilisateurs interagissent avec les fonctionnalités d’authentification, telles que l’authentification à deux facteurs. Cette observabilité est particulièrement utile pour les applications avec des exigences de sécurité strictes ou celles qui rencontrent un trafic d’authentification élevé.

Pour plus d’informations sur les métriques disponibles et leur utilisation, consultez ASP.NET Core métriques.

Générer automatiquement les modèles Register, Login, LogOut et RegisterConfirmation

Ajoutez les fichiers Register, Login, LogOut et RegisterConfirmation. Suivez les instructions de l'identité Razor pour générer le code avec les instructions indiquées dans cette section.

Examiner le registre

Quand un utilisateur clique sur le bouton d’inscription sur la page Register, l’action RegisterModel.OnPostAsync est appelée. L’utilisateur est créé par CreateAsync(TUser) sur l’objet _userManager :

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");
    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
                                          .ToList();
    if (ModelState.IsValid)
    {
        var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
        var result = await _userManager.CreateAsync(user, Input.Password);
        if (result.Succeeded)
        {
            _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            var callbackUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = user.Id, code = code },
                protocol: Request.Scheme);

            await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

            if (_userManager.Options.SignIn.RequireConfirmedAccount)
            {
                return RedirectToPage("RegisterConfirmation", 
                                      new { email = Input.Email });
            }
            else
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl);
            }
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }

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

Désactiver la vérification du compte par défaut

Avec les modèles par défaut, l’utilisateur est redirigé vers Account.RegisterConfirmation où il peut sélectionner un lien pour que le compte soit confirmé. La valeur par défaut Account.RegisterConfirmation est utilisée uniquement à des fins de test. La vérification automatique du compte doit être désactivée dans une application de production.

Pour exiger un compte confirmé et empêcher la connexion immédiate lors de l’inscription, définissez DisplayConfirmAccountLink = false dans /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs :

[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IEmailSender _sender;

    public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
    {
        _userManager = userManager;
        _sender = sender;
    }

    public string Email { get; set; }

    public bool DisplayConfirmAccountLink { get; set; }

    public string EmailConfirmationUrl { get; set; }

    public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
    {
        if (email == null)
        {
            return RedirectToPage("/Index");
        }

        var user = await _userManager.FindByEmailAsync(email);
        if (user == null)
        {
            return NotFound($"Unable to load user with email '{email}'.");
        }

        Email = email;
        // Once you add a real email sender, you should remove this code that lets you confirm the account
        DisplayConfirmAccountLink = false;
        if (DisplayConfirmAccountLink)
        {
            var userId = await _userManager.GetUserIdAsync(user);
            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            EmailConfirmationUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
                protocol: Request.Scheme);
        }

        return Page();
    }
}

Se connecter

Le formulaire de connexion s’affiche dans les cas suivants :

  • Le lien Se connecter est sélectionné.
  • Un utilisateur tente d'accéder à une page restreinte qu'il n'est pas autorisé à accéder ou s'il n'a pas été authentifié par le système.

Quand le formulaire de la page de connexion est envoyé, l’action OnPostAsync est appelée. PasswordSignInAsync est appelé sur l’objet _signInManager.

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, 
        // set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email,
                           Input.Password, Input.RememberMe, lockoutOnFailure: true);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new
            {
                ReturnUrl = returnUrl,
                RememberMe = Input.RememberMe
            });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

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

Pour plus d’informations sur la façon de prendre des décisions d’autorisation, consultez Introduction de l’autorisation dans ASP.NET Core.

Se déconnecter

Le lien de déconnexion appelle l’action LogoutModel.OnPost.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace WebApp1.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return RedirectToPage();
            }
        }
    }
}

Dans le code précédent, le code return RedirectToPage(); doit être une redirection afin que le navigateur effectue une nouvelle requête et que l’identité de l’utilisateur soit mise à jour.

SignOutAsync efface les revendications de l’utilisateur stockées dans un cookie.

Post est spécifié dans Pages/Shared/_LoginPartial.cshtml :

@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    <li class="nav-item">
        <a  class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" 
                                              title="Manage">Hello @User.Identity.Name!</a>
    </li>
    <li class="nav-item">
        <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" 
                                  asp-route-returnUrl="@Url.Page("/", new { area = "" })" 
                                  method="post" >
            <button  type="submit" class="nav-link btn btn-link text-dark">Logout</button>
        </form>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
}
</ul>

Test Identity

Les modèles de project web par défaut autorisent des access anonymes aux pages d’accueil. Pour tester Identity, ajoutez [Authorize] :

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace WebApp1.Pages
{
    [Authorize]
    public class PrivacyModel : PageModel
    {
        private readonly ILogger<PrivacyModel> _logger;

        public PrivacyModel(ILogger<PrivacyModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
        }
    }
}

Si vous êtes connecté, déconnectez-vous. Exécutez l'application et sélectionnez le lien Privacy. Vous êtes redirigé vers la page de connexion.

Explorer Identity

Pour explorer Identity en détail :

Composants Identity

Tous les packages NuGet dépendant de Identity sont inclus dans l’infrastructure partagée ASP.NET Core.

Le package principal pour Identity est Microsoft.AspNetCore.Identity. Ce package contient l’ensemble principal d’interfaces pour ASP.NET Core Identity et est inclus par Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Migration vers ASP.NET Core Identity

Pour plus d’informations et pour obtenir de l’aide sur la migration de votre magasin Identity existant, consultez l’article Migrer l’authentification et Identity.

Définition de la force du mot de passe

Consultez la section sur la configuration pour obtenir un exemple qui définit les exigences minimales relatives aux mots de passe.

AddDefaultIdentity et AddIdentity

AddDefaultIdentity a été introduit dans ASP.NET Core 2.1. Appeler AddDefaultIdentity revient à appeler ce qui suit :

Pour plus d’informations, consultez AddDefaultIdentity source.

Empêcher la publication de ressources Identity statiques

Pour empêcher la publication de ressources statiques Identity (feuilles de style et fichiers JavaScript pour Identity UI) à la racine web, ajoutez la propriété ResolveStaticWebAssetsInputsDependsOn suivante et la cible RemoveIdentityAssets au fichier de projet de l'application :

<PropertyGroup>
  <ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>

<Target Name="RemoveIdentityAssets">
  <ItemGroup>
    <StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
  </ItemGroup>
</Target>

Étapes suivantes

Par Rick Anderson

ASP.NET Core Identity :

  • Est une API qui prend en charge la fonctionnalité de connexion par interface utilisateur.
  • Gère les utilisateurs, les mots de passe, les données de profil, les rôles, les revendications, les jetons, la confirmation par e-mail, etc.

Les utilisateurs peuvent créer un compte avec les informations de connexion stockées dans Identity ou utiliser un fournisseur de connexion externe. Les fournisseurs de connexion externes pris en charge incluent Facebook, Google, Compte Microsoft et Twitter.

Pour plus d’informations sur la façon d’exiger l’authentification pour tous les utilisateurs de l’application, consultez Créer une application ASP.NET Core avec des données utilisateur protégées par autorisation.

Le code source Identity est disponible sur GitHub. Générez l’ossature Identity et affichez les fichiers générés pour examiner comment le modèle interagit avec Identity.

Identity est généralement configuré à l’aide d’une base de données SQL Server pour stocker les noms d’utilisateur, les mots de passe et les données de profil. Vous pouvez également utiliser un autre magasin persistant, par exemple Azure Table Storage.

Dans cette rubrique, vous allez apprendre à utiliser Identity pour inscrire, connecter et déconnecter un utilisateur. Remarque : les modèles traitent le nom d’utilisateur et l’adresse e-mail comme étant identiques pour les utilisateurs. Pour obtenir des instructions plus détaillées sur la création d’applications qui utilisent Identity, consultez la section Étapes suivantes.

ASP.NET Core Identity n'est pas lié à la plateforme d'identités Microsoft. La plateforme d’identités Microsoft est la suivante :

  • Évolution de la plateforme de développement Azure Active Directory (Azure AD).
  • Solution d’identité alternative pour l’authentification et l’autorisation dans ASP.NET Core applications.

ASP.NET Core Identity ajoute la fonctionnalité de connexion de l’interface utilisateur aux applications web ASP.NET Core. Pour sécuriser les API web et SPA, utilisez l’une des options suivantes :

Duende Identity Server est une infrastructure OpenID Connect et OAuth 2.0 pour ASP.NET Core. Duende Identity Server active les fonctionnalités de sécurité suivantes :

  • Authentification en tant que service (AaaS)
  • Authentification/déconnexion unique (SSO) sur plusieurs types d’applications
  • Contrôle d'accès pour les API
  • Passerelle de fédération

Important

Duende Software peut vous demander de payer des frais de licence pour une utilisation en production de Duende Identity Server. Pour plus d’informations, consultez Migrate de ASP.NET Core dans .NET 5 à .NET 6.

Pour plus d’informations, consultez la documentation Duende Identity Server (site web de Duende Software).

Consultez ou téléchargez l’exemple de code (comment télécharger).

Créer une application web avec authentification

Créez une application web ASP.NET Core project avec des comptes d’utilisateur individuels.

  • Sélectionnez le modèle ASP.NET Core Web App. Nommez le projet WebApp1 pour avoir le même espace de noms que le projet de téléchargement. Cliquez sur OK.
  • Dans l’entrée Type d’authentification, sélectionnez Comptes d’utilisateur individuels.

Le project généré fournit ASP.NET Core Identity en tant que bibliothèque de classes Razor. La bibliothèque de classes IdentityRazor expose les points de terminaison avec la zone Identity. Par exemple:

  • /Identity/Account/Login
  • /Identity/Account/Logout
  • /Identity/Compte/Gérer

Appliquer des migrations

Appliquez les migrations pour initialiser la base de données.

Exécutez la commande suivante dans la console Gestionnaire de package (PMC) :

Update-Database

Tester l’inscription et la connexion

Exécutez l’application et inscrivez un utilisateur. Selon la taille de votre écran, vous devrez peut-être sélectionner le bouton bascule de navigation pour afficher les liens d’inscription et de connexion.

Afficher la base de données Identity

  • Dans le menu View, sélectionnez SQL Server Explorateur d'objets (SSOX).
  • Accédez à (localdb)MSSQLLocalDB(SQL Server 13). Cliquez avec le bouton droit sur dbo.AspNetUsers>Afficher les données :

Menu contextuel de la table AspNetUsers dans SQL Server Explorateur d'objets

Configurer les services Identity

Les services sont ajoutés dans Program.cs. Le modèle classique consiste à appeler les méthodes dans l’ordre suivant :

  1. Add{Service}
  2. builder.Services.Configure{Service}
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using WebApp1.Data;

var builder = WebApplication.CreateBuilder(args);

var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

builder.Services.Configure<IdentityOptions>(options =>
{
    // Password settings.
    options.Password.RequireDigit = true;
    options.Password.RequireLowercase = true;
    options.Password.RequireNonAlphanumeric = true;
    options.Password.RequireUppercase = true;
    options.Password.RequiredLength = 6;
    options.Password.RequiredUniqueChars = 1;

    // Lockout settings.
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.AllowedForNewUsers = true;

    // User settings.
    options.User.AllowedUserNameCharacters =
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
    options.User.RequireUniqueEmail = false;
});

builder.Services.ConfigureApplicationCookie(options =>
{
    // Cookie settings
    options.Cookie.HttpOnly = true;
    options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

    options.LoginPath = "/Identity/Account/Login";
    options.AccessDeniedPath = "/Identity/Account/AccessDenied";
    options.SlidingExpiration = true;
});

var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

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

app.MapRazorPages();

app.Run();

Le code précédent configure Identity avec les valeurs d’option par défaut. Les services sont accessibles à l’application au moyen de l’injection de dépendances.

Identity est activé en appelant UseAuthentication. UseAuthentication ajoute un intergiciel d’authentification au pipeline de requêtes.

L’application générée par un modèle n’utilise pas l’autorisation. app.UseAuthorization est inclus pour s’assurer qu’il est ajouté dans l’ordre correct si l’application ajoute une autorisation. UseRouting, UseAuthentication et UseAuthorization doivent être appelés dans l’ordre indiqué dans le code précédent.

Pour plus d’informations sur IdentityOptions, consultez les articles IdentityOptions et Démarrage d’une application.

Générer automatiquement les modèles Register, Login, LogOut et RegisterConfirmation

Ajoutez les fichiers Register, Login, LogOut et RegisterConfirmation. Suivez les instructions de l'identité Razor pour générer le code avec les instructions indiquées dans cette section.

Examiner le registre

Quand un utilisateur clique sur le bouton d’inscription sur la page Register, l’action RegisterModel.OnPostAsync est appelée. L’utilisateur est créé par CreateAsync(TUser) sur l’objet _userManager :

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");
    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
                                          .ToList();
    if (ModelState.IsValid)
    {
        var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
        var result = await _userManager.CreateAsync(user, Input.Password);
        if (result.Succeeded)
        {
            _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            var callbackUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = user.Id, code = code },
                protocol: Request.Scheme);

            await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

            if (_userManager.Options.SignIn.RequireConfirmedAccount)
            {
                return RedirectToPage("RegisterConfirmation", 
                                      new { email = Input.Email });
            }
            else
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl);
            }
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }

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

Désactiver la vérification du compte par défaut

Avec les modèles par défaut, l’utilisateur est redirigé vers Account.RegisterConfirmation où il peut sélectionner un lien pour que le compte soit confirmé. La valeur par défaut Account.RegisterConfirmation est utilisée uniquement à des fins de test. La vérification automatique du compte doit être désactivée dans une application de production.

Pour exiger un compte confirmé et empêcher la connexion immédiate lors de l’inscription, définissez DisplayConfirmAccountLink = false dans /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs :

[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IEmailSender _sender;

    public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
    {
        _userManager = userManager;
        _sender = sender;
    }

    public string Email { get; set; }

    public bool DisplayConfirmAccountLink { get; set; }

    public string EmailConfirmationUrl { get; set; }

    public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
    {
        if (email == null)
        {
            return RedirectToPage("/Index");
        }

        var user = await _userManager.FindByEmailAsync(email);
        if (user == null)
        {
            return NotFound($"Unable to load user with email '{email}'.");
        }

        Email = email;
        // Once you add a real email sender, you should remove this code that lets you confirm the account
        DisplayConfirmAccountLink = false;
        if (DisplayConfirmAccountLink)
        {
            var userId = await _userManager.GetUserIdAsync(user);
            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            EmailConfirmationUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
                protocol: Request.Scheme);
        }

        return Page();
    }
}

Se connecter

Le formulaire de connexion s’affiche dans les cas suivants :

  • Le lien Se connecter est sélectionné.
  • Un utilisateur tente d'accéder à une page restreinte qu'il n'est pas autorisé à accéder ou s'il n'a pas été authentifié par le système.

Quand le formulaire de la page de connexion est envoyé, l’action OnPostAsync est appelée. PasswordSignInAsync est appelé sur l’objet _signInManager.

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, 
        // set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email,
                           Input.Password, Input.RememberMe, lockoutOnFailure: true);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new
            {
                ReturnUrl = returnUrl,
                RememberMe = Input.RememberMe
            });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

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

Pour plus d’informations sur la façon de prendre des décisions d’autorisation, consultez Introduction de l’autorisation dans ASP.NET Core.

Se déconnecter

Le lien de déconnexion appelle l’action LogoutModel.OnPost.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace WebApp1.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return RedirectToPage();
            }
        }
    }
}

Dans le code précédent, le code return RedirectToPage(); doit être une redirection afin que le navigateur effectue une nouvelle requête et que l’identité de l’utilisateur soit mise à jour.

SignOutAsync efface les revendications de l’utilisateur stockées dans un cookie.

Post est spécifié dans Pages/Shared/_LoginPartial.cshtml :

@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    <li class="nav-item">
        <a  class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" 
                                              title="Manage">Hello @User.Identity.Name!</a>
    </li>
    <li class="nav-item">
        <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" 
                                  asp-route-returnUrl="@Url.Page("/", new { area = "" })" 
                                  method="post" >
            <button  type="submit" class="nav-link btn btn-link text-dark">Logout</button>
        </form>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
}
</ul>

Test Identity

Les modèles de project web par défaut autorisent des access anonymes aux pages d’accueil. Pour tester Identity, ajoutez [Authorize] :

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace WebApp1.Pages
{
    [Authorize]
    public class PrivacyModel : PageModel
    {
        private readonly ILogger<PrivacyModel> _logger;

        public PrivacyModel(ILogger<PrivacyModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
        }
    }
}

Si vous êtes connecté, déconnectez-vous. Exécutez l'application et sélectionnez le lien Privacy. Vous êtes redirigé vers la page de connexion.

Explorer Identity

Pour explorer Identity en détail :

Composants Identity

Tous les packages NuGet dépendant de Identity sont inclus dans l’infrastructure partagée ASP.NET Core.

Le package principal pour Identity est Microsoft.AspNetCore.Identity. Ce package contient l’ensemble principal d’interfaces pour ASP.NET Core Identity et est inclus par Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Migration vers ASP.NET Core Identity

Pour plus d’informations et pour obtenir de l’aide sur la migration de votre magasin Identity existant, consultez l’article Migrer l’authentification et Identity.

Définition de la force du mot de passe

Consultez la section sur la configuration pour obtenir un exemple qui définit les exigences minimales relatives aux mots de passe.

AddDefaultIdentity et AddIdentity

AddDefaultIdentity a été introduit dans ASP.NET Core 2.1. Appeler AddDefaultIdentity revient à appeler ce qui suit :

Pour plus d’informations, consultez AddDefaultIdentity source.

Empêcher la publication de ressources Identity statiques

Pour empêcher la publication de ressources statiques Identity (feuilles de style et fichiers JavaScript pour Identity UI) à la racine web, ajoutez la propriété ResolveStaticWebAssetsInputsDependsOn suivante et la cible RemoveIdentityAssets au fichier de projet de l'application :

<PropertyGroup>
  <ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>

<Target Name="RemoveIdentityAssets">
  <ItemGroup>
    <StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
  </ItemGroup>
</Target>

Étapes suivantes

Par Rick Anderson

ASP.NET Core Identity :

  • Est une API qui prend en charge la fonctionnalité de connexion par interface utilisateur.
  • Gère les utilisateurs, les mots de passe, les données de profil, les rôles, les revendications, les jetons, la confirmation par e-mail, etc.

Les utilisateurs peuvent créer un compte avec les informations de connexion stockées dans Identity ou utiliser un fournisseur de connexion externe. Les fournisseurs de connexion externes pris en charge incluent Facebook, Google, Compte Microsoft et Twitter.

Pour plus d’informations sur la façon d’exiger l’authentification pour tous les utilisateurs de l’application, consultez Créer une application ASP.NET Core avec des données utilisateur protégées par autorisation.

Le code source Identity est disponible sur GitHub. Générez l’ossature Identity et affichez les fichiers générés pour examiner comment le modèle interagit avec Identity.

Identity est généralement configuré à l’aide d’une base de données SQL Server pour stocker les noms d’utilisateur, les mots de passe et les données de profil. Vous pouvez également utiliser un autre magasin persistant, par exemple Azure Table Storage.

Dans cette rubrique, vous allez apprendre à utiliser Identity pour inscrire, connecter et déconnecter un utilisateur. Remarque : les modèles traitent le nom d’utilisateur et l’adresse e-mail comme étant identiques pour les utilisateurs. Pour obtenir des instructions plus détaillées sur la création d’applications qui utilisent Identity, consultez la section Étapes suivantes.

Plateforme d’identitésMicrosoft est :

  • Évolution de la plateforme de développement Azure Active Directory (Azure AD).
  • Solution d’identité alternative pour l’authentification et l’autorisation dans ASP.NET Core applications.
  • Non lié à ASP.NET Core Identity.

ASP.NET Core Identity ajoute la fonctionnalité de connexion de l’interface utilisateur aux applications web ASP.NET Core. Pour sécuriser les API web et SPA, utilisez l’une des options suivantes :

Duende IdentityServer est une infrastructure OpenID Connect et OAuth 2.0 pour ASP.NET Core. Duende IdentityServer active les fonctionnalités de sécurité suivantes :

  • Authentification en tant que service (AaaS)
  • Authentification/déconnexion unique (SSO) sur plusieurs types d’applications
  • Contrôle d'accès pour les API
  • Passerelle de fédération

Pour plus d’informations, consultez la section Vue d’ensemble de Duende IdentityServer.

Pour plus d’informations sur les autres fournisseurs d’authentification, consultez les options d’authentification de la communauté OSS pour ASP.NET Core

Consultez ou téléchargez l’exemple de code (comment télécharger).

Créer une application web avec authentification

Créez une application web ASP.NET Core project avec des comptes d’utilisateur individuels.

  • Sélectionnez File>New>Project.
  • Sélectionnez ASP.NET Core Application web. Nommez le projet WebApp1 pour avoir le même espace de noms que le projet de téléchargement. Cliquez sur OK.
  • Sélectionnez une application ASP.NET Core Web, puis sélectionnez Change Authentication.
  • Sélectionnez Comptes d’utilisateur individuels, puis cliquez sur OK.

Le project généré fournit ASP.NET Core Identity en tant que bibliothèque de classes Razor. La bibliothèque de classes IdentityRazor expose les points de terminaison avec la zone Identity. Par exemple:

  • /Identity/Account/Login
  • /Identity/Account/Logout
  • /Identity/Compte/Gérer

Appliquer des migrations

Appliquez les migrations pour initialiser la base de données.

Exécutez la commande suivante dans la console Gestionnaire de package (PMC) :

PM> Update-Database

Tester l’inscription et la connexion

Exécutez l’application et inscrivez un utilisateur. Selon la taille de votre écran, vous devrez peut-être sélectionner le bouton bascule de navigation pour afficher les liens d’inscription et de connexion.

Afficher la base de données Identity

  • Dans le menu View, sélectionnez SQL Server Explorateur d'objets (SSOX).
  • Accédez à (localdb)MSSQLLocalDB(SQL Server 13). Cliquez avec le bouton droit sur dbo.AspNetUsers>Afficher les données :

Menu contextuel de la table AspNetUsers dans SQL Server Explorateur d'objets

Configurer les services Identity

Les services sont ajoutés dans ConfigureServices. Le modèle par défaut consiste à appeler toutes les méthodes Add{Service}, puis toutes les méthodes services.Configure{Service}.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
     // options.UseSqlite(
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();
    services.AddRazorPages();

    services.Configure<IdentityOptions>(options =>
    {
        // Password settings.
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequireNonAlphanumeric = true;
        options.Password.RequireUppercase = true;
        options.Password.RequiredLength = 6;
        options.Password.RequiredUniqueChars = 1;

        // Lockout settings.
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
        options.Lockout.AllowedForNewUsers = true;

        // User settings.
        options.User.AllowedUserNameCharacters =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
        options.User.RequireUniqueEmail = false;
    });

    services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

        options.LoginPath = "/Identity/Account/Login";
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        options.SlidingExpiration = true;
    });
}

Le code mise en surbrillance précédent configure Identity avec les valeurs d’option par défaut. Les services sont accessibles à l’application au moyen de l’injection de dépendances.

Identity est activé en appelant UseAuthentication. UseAuthentication ajoute un intergiciel d’authentification au pipeline de requêtes.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseDatabaseErrorPage();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

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

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}
public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        // options.UseSqlite(
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDatabaseDeveloperPageExceptionFilter();
    services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
        .AddEntityFrameworkStores<ApplicationDbContext>();
    services.AddRazorPages();

    services.Configure<IdentityOptions>(options =>
    {
        // Password settings.
        options.Password.RequireDigit = true;
        options.Password.RequireLowercase = true;
        options.Password.RequireNonAlphanumeric = true;
        options.Password.RequireUppercase = true;
        options.Password.RequiredLength = 6;
        options.Password.RequiredUniqueChars = 1;

        // Lockout settings.
        options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
        options.Lockout.MaxFailedAccessAttempts = 5;
        options.Lockout.AllowedForNewUsers = true;

        // User settings.
        options.User.AllowedUserNameCharacters =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
        options.User.RequireUniqueEmail = false;
    });

    services.ConfigureApplicationCookie(options =>
    {
        // Cookie settings
        options.Cookie.HttpOnly = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(5);

        options.LoginPath = "/Identity/Account/Login";
        options.AccessDeniedPath = "/Identity/Account/AccessDenied";
        options.SlidingExpiration = true;
    });
}

Le code précédent configure Identity avec les valeurs d’option par défaut. Les services sont accessibles à l’application au moyen de l’injection de dépendances.

Identity est activé en appelant UseAuthentication. UseAuthentication ajoute un intergiciel d’authentification au pipeline de requêtes.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseMigrationsEndPoint();
    }
    else
    {
        app.UseExceptionHandler("/Error");
        app.UseHsts();
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

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

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
    });
}

L’application générée par un modèle n’utilise pas l’autorisation. app.UseAuthorization est inclus pour s’assurer qu’il est ajouté dans l’ordre correct si l’application ajoute une autorisation. UseRouting, UseAuthentication, UseAuthorization et UseEndpoints doivent être appelés dans l’ordre indiqué dans le code précédent.

Pour plus d’informations sur IdentityOptions et Startup, consultez les articles IdentityOptions et Démarrage d’une application.

Générer automatiquement les modèles Register, Login, LogOut et RegisterConfirmation

Ajoutez les fichiers Register, Login, LogOut et RegisterConfirmation. Suivez les instructions de l'identité Razor pour générer le code avec les instructions indiquées dans cette section.

Examiner le registre

Quand un utilisateur clique sur le bouton d’inscription sur la page Register, l’action RegisterModel.OnPostAsync est appelée. L’utilisateur est créé par CreateAsync(TUser) sur l’objet _userManager :

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");
    ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
                                          .ToList();
    if (ModelState.IsValid)
    {
        var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
        var result = await _userManager.CreateAsync(user, Input.Password);
        if (result.Succeeded)
        {
            _logger.LogInformation("User created a new account with password.");

            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            var callbackUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = user.Id, code = code },
                protocol: Request.Scheme);

            await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

            if (_userManager.Options.SignIn.RequireConfirmedAccount)
            {
                return RedirectToPage("RegisterConfirmation", 
                                      new { email = Input.Email });
            }
            else
            {
                await _signInManager.SignInAsync(user, isPersistent: false);
                return LocalRedirect(returnUrl);
            }
        }
        foreach (var error in result.Errors)
        {
            ModelState.AddModelError(string.Empty, error.Description);
        }
    }

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

Désactiver la vérification du compte par défaut

Avec les modèles par défaut, l’utilisateur est redirigé vers Account.RegisterConfirmation où il peut sélectionner un lien pour que le compte soit confirmé. La valeur par défaut Account.RegisterConfirmation est utilisée uniquement à des fins de test. La vérification automatique du compte doit être désactivée dans une application de production.

Pour exiger un compte confirmé et empêcher la connexion immédiate lors de l’inscription, définissez DisplayConfirmAccountLink = false dans /Areas/Identity/Pages/Account/RegisterConfirmation.cshtml.cs :

[AllowAnonymous]
public class RegisterConfirmationModel : PageModel
{
    private readonly UserManager<IdentityUser> _userManager;
    private readonly IEmailSender _sender;

    public RegisterConfirmationModel(UserManager<IdentityUser> userManager, IEmailSender sender)
    {
        _userManager = userManager;
        _sender = sender;
    }

    public string Email { get; set; }

    public bool DisplayConfirmAccountLink { get; set; }

    public string EmailConfirmationUrl { get; set; }

    public async Task<IActionResult> OnGetAsync(string email, string returnUrl = null)
    {
        if (email == null)
        {
            return RedirectToPage("/Index");
        }

        var user = await _userManager.FindByEmailAsync(email);
        if (user == null)
        {
            return NotFound($"Unable to load user with email '{email}'.");
        }

        Email = email;
        // Once you add a real email sender, you should remove this code that lets you confirm the account
        DisplayConfirmAccountLink = false;
        if (DisplayConfirmAccountLink)
        {
            var userId = await _userManager.GetUserIdAsync(user);
            var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
            code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
            EmailConfirmationUrl = Url.Page(
                "/Account/ConfirmEmail",
                pageHandler: null,
                values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
                protocol: Request.Scheme);
        }

        return Page();
    }
}

Se connecter

Le formulaire de connexion s’affiche dans les cas suivants :

  • Le lien Se connecter est sélectionné.
  • Un utilisateur tente d'accéder à une page restreinte qu'il n'est pas autorisé à accéder ou s'il n'a pas été authentifié par le système.

Quand le formulaire de la page de connexion est envoyé, l’action OnPostAsync est appelée. PasswordSignInAsync est appelé sur l’objet _signInManager.

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
    returnUrl = returnUrl ?? Url.Content("~/");

    if (ModelState.IsValid)
    {
        // This doesn't count login failures towards account lockout
        // To enable password failures to trigger account lockout, 
        // set lockoutOnFailure: true
        var result = await _signInManager.PasswordSignInAsync(Input.Email,
                           Input.Password, Input.RememberMe, lockoutOnFailure: true);
        if (result.Succeeded)
        {
            _logger.LogInformation("User logged in.");
            return LocalRedirect(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            return RedirectToPage("./LoginWith2fa", new
            {
                ReturnUrl = returnUrl,
                RememberMe = Input.RememberMe
            });
        }
        if (result.IsLockedOut)
        {
            _logger.LogWarning("User account locked out.");
            return RedirectToPage("./Lockout");
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return Page();
        }
    }

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

Pour plus d’informations sur la façon de prendre des décisions d’autorisation, consultez Introduction de l’autorisation dans ASP.NET Core.

Se déconnecter

Le lien de déconnexion appelle l’action LogoutModel.OnPost.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace WebApp1.Areas.Identity.Pages.Account
{
    [AllowAnonymous]
    public class LogoutModel : PageModel
    {
        private readonly SignInManager<IdentityUser> _signInManager;
        private readonly ILogger<LogoutModel> _logger;

        public LogoutModel(SignInManager<IdentityUser> signInManager, ILogger<LogoutModel> logger)
        {
            _signInManager = signInManager;
            _logger = logger;
        }

        public void OnGet()
        {
        }

        public async Task<IActionResult> OnPost(string returnUrl = null)
        {
            await _signInManager.SignOutAsync();
            _logger.LogInformation("User logged out.");
            if (returnUrl != null)
            {
                return LocalRedirect(returnUrl);
            }
            else
            {
                return RedirectToPage();
            }
        }
    }
}

Dans le code précédent, le code return RedirectToPage(); doit être une redirection afin que le navigateur effectue une nouvelle requête et que l’identité de l’utilisateur soit mise à jour.

SignOutAsync efface les revendications de l’utilisateur stockées dans un cookie.

Post est spécifié dans Pages/Shared/_LoginPartial.cshtml :

@using Microsoft.AspNetCore.Identity
@inject SignInManager<IdentityUser> SignInManager
@inject UserManager<IdentityUser> UserManager

<ul class="navbar-nav">
@if (SignInManager.IsSignedIn(User))
{
    <li class="nav-item">
        <a  class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Manage/Index" 
                                              title="Manage">Hello @User.Identity.Name!</a>
    </li>
    <li class="nav-item">
        <form class="form-inline" asp-area="Identity" asp-page="/Account/Logout" 
                                  asp-route-returnUrl="@Url.Page("/", new { area = "" })" 
                                  method="post" >
            <button  type="submit" class="nav-link btn btn-link text-dark">Logout</button>
        </form>
    </li>
}
else
{
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Register">Register</a>
    </li>
    <li class="nav-item">
        <a class="nav-link text-dark" asp-area="Identity" asp-page="/Account/Login">Login</a>
    </li>
}
</ul>

Test Identity

Les modèles de project web par défaut autorisent des access anonymes aux pages d’accueil. Pour tester Identity, ajoutez [Authorize] :

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;

namespace WebApp1.Pages
{
    [Authorize]
    public class PrivacyModel : PageModel
    {
        private readonly ILogger<PrivacyModel> _logger;

        public PrivacyModel(ILogger<PrivacyModel> logger)
        {
            _logger = logger;
        }

        public void OnGet()
        {
        }
    }
}

Si vous êtes connecté, déconnectez-vous. Exécutez l'application et sélectionnez le lien Privacy. Vous êtes redirigé vers la page de connexion.

Explorer Identity

Pour explorer Identity en détail :

Composants Identity

Tous les packages NuGet dépendant de Identity sont inclus dans l’infrastructure partagée ASP.NET Core.

Le package principal pour Identity est Microsoft.AspNetCore.Identity. Ce package contient l’ensemble principal d’interfaces pour ASP.NET Core Identity et est inclus par Microsoft.AspNetCore.Identity.EntityFrameworkCore.

Migration vers ASP.NET Core Identity

Pour plus d’informations et pour obtenir de l’aide sur la migration de votre magasin Identity existant, consultez l’article Migrer l’authentification et Identity.

Définition de la force du mot de passe

Consultez la section sur la configuration pour obtenir un exemple qui définit les exigences minimales relatives aux mots de passe.

Empêcher la publication de ressources Identity statiques

Pour empêcher la publication de ressources statiques Identity (feuilles de style et fichiers JavaScript pour Identity UI) à la racine web, ajoutez la propriété ResolveStaticWebAssetsInputsDependsOn suivante et la cible RemoveIdentityAssets au fichier de projet de l'application :

<PropertyGroup>
  <ResolveStaticWebAssetsInputsDependsOn>RemoveIdentityAssets</ResolveStaticWebAssetsInputsDependsOn>
</PropertyGroup>

<Target Name="RemoveIdentityAssets">
  <ItemGroup>
    <StaticWebAsset Remove="@(StaticWebAsset)" Condition="%(SourceId) == 'Microsoft.AspNetCore.Identity.UI'" />
  </ItemGroup>
</Target>

Étapes suivantes