Authentification et autorisation avec ASP.NET Core Blazor

Remarque

Ceci n’est pas la dernière version de cet article. Pour la version actuelle, consultez la version .NET 8 de cet article.

Important

Ces informations portent sur la préversion du produit, qui est susceptible d’être en grande partie modifié avant sa commercialisation. Microsoft n’offre aucune garantie, expresse ou implicite, concernant les informations fournies ici.

Pour la version actuelle, consultez la version .NET 8 de cet article.

Cet article décrit la prise en charge d’ASP.NET Core pour la configuration et la gestion de la sécurité dans les applications Blazor.

Les scénarios de sécurité diffèrent entre le code d’autorisation s’exécutant côté serveur et celui qui s’exécute côté client dans les applications Blazor. Pour le code d’autorisation qui s’exécute sur le serveur, les vérifications d’autorisation sont en mesure d’appliquer des règles d’accès pour des zones de l’application et des composants. Comme l’exécution du code côté client peut être falsifiée, vous n’avez pas la certitude que le code d’autorisation s’exécutant sur le client va appliquer absolument des règles d’accès ou contrôler l’affichage du contenu côté client.

Si l’application de la règle d’autorisation doit être garantie, n’implémentez pas les vérifications d’autorisation dans le code côté client. Créez une application web Blazor qui s’appuie seulement sur le rendu côté serveur pour les vérifications d’autorisation et l’application des règles.

Les conventions d’autorisation Razor Pages ne s’appliquent pas aux composants Razor routables. Si un composant Razor non routable est incorporé dans une page d’une application Razor Pages, les conventions d’autorisation de la page affectent indirectement le composant Razor ainsi que le reste du contenu de la page.

Si l’application des règles d’autorisation et la sécurité des données et du code doivent être garanties, ne développez pas une application côté client. Créez une application Blazor Server.

Les conventions d’autorisation Razor Pages ne s’appliquent pas aux composants Razor routables. Si un composant Razor non routable est incorporé dans une page d’une application Razor Pages, les conventions d’autorisation de la page affectent indirectement le composant Razor ainsi que le reste du contenu de la page.

ASP.NET Core Identity est conçu pour fonctionner dans le contexte de la communication des requêtes et des réponses HTTP, qui n’est généralement pas le modèle de communication client-serveur de l’application Blazor. Les applications ASP.NET Core qui utilisent ASP.NET Core Identity pour la gestion des utilisateurs doivent utiliser Razor Pages plutôt que les composants Razor pour l’interface utilisateur en rapport avec Identity, notamment pour l’inscription des utilisateurs, la connexion, la déconnexion et d’autres tâches de gestion des utilisateurs. La génération de composants Razor qui gèrent directement des tâches Identity est possible pour plusieurs scénarios, mais elle n’est pas recommandée ou prise en charge par Microsoft.

Les abstractions ASP.NET Core, telles que SignInManager<TUser> et UserManager<TUser>, ne sont pas prises en charge dans les composants Razor. Pour plus d’informations sur l’utilisation d’ASP.NET Core Identity avec Blazor, consultez Générer automatiquement des modèles ASP.NET Core Identity dans une application Blazor coté serveur .

Remarque

Les exemples de code de cet article adoptent les types référence null (NRT) et l’analyse statique de l’état null du compilateur .NET, qui sont pris en charge dans ASP.NET Core dans .NET 6 ou une version ultérieure. Lorsque vous ciblez ASP.NET Core 5.0 ou version antérieure, supprimez la désignation de type nul (?) des exemples de cet article.

Prise en charge d’Antiforgery

Le modèle Blazor :

Le composant AntiforgeryToken affiche un jeton anti-falsification en tant que champ masqué, et ce composant est automatiquement ajouté aux instances de formulaire (EditForm). Pour plus d’informations, consultez Vue d’ensemble des formulaires Blazor ASP.NET Core.

Le service AntiforgeryStateProvider fournit un accès à un jeton anti-falsification associé à la session active. Injectez le service et appelez sa méthode GetAntiforgeryToken() pour obtenir le AntiforgeryRequestToken actuel. Pour plus d’informations, consultez Appeler une API web à partir d’une application Blazor ASP.NET Core.

Blazor stocke les jetons de requête dans l’état du composant, ce qui garantit que les jetons anti-falsification sont disponibles pour les composants interactifs, même s’ils n’ont pas accès à la requête.

Remarque

L’atténuation Antiforgery n’est requise que lors de l’envoi de données de formulaire au serveur encodé en tant que application/x-www-form-urlencoded, multipart/form-data ou text/plain, étant donné qu’il s’agit des seulstypes de chiffrement de formulaire valides.

Pour plus d’informations, consultez les ressources suivantes :

Authentification

Blazor utilise les mécanismes d’authentification ASP.NET Core existants pour établir l’identité de l’utilisateur. Le mécanisme exact dépend de la façon dont l’application Blazor est hébergée, côté serveur ou côté client.

Authentification Blazor côté serveur

Le Blazor rendu de façon interactive côté serveur fonctionne sur une connexion SignalR avec le client. L’authentification dans les applications basées sur SignalR est gérée au moment où la connexion est établie. L’authentification peut être basée sur un cookie ou un autre jeton du porteur, mais l’authentification est gérée via le hub SignalR et entièrement au sein du circuit.

Le service AuthenticationStateProvider intégré obtient des données d’état d’authentification du HttpContext.User d’ASP.NET Core. C’est ainsi que l’état d’authentification s’intègre avec les mécanismes d’authentification ASP.NET Core.

IHttpContextAccessor/HttpContext dans les composants Razor

IHttpContextAccessor doit être évité avec le rendu interactif, car il n’existe pas de HttpContext valide disponible.

IHttpContextAccessor peut être utilisé pour les composants rendus statiquement sur le serveur. Toutefois, nous vous recommandons de l’éviter si possible.

HttpContext peut être utilisé comme paramètre en cascade uniquement dans les composants racines rendus statiquement pour les tâches générales, telles que l’inspection et la modification d’en-têtes ou d’autres propriétés dans le composant App (Components/App.razor). La valeur est toujours null pour le rendu interactif.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

Pour les scénarios où HttpContext est requis dans les composants interactifs, nous vous recommandons de transmettre les données via l’état du composant persistant à partir du serveur. Pour plus d’informations, consultez Autres scénarios de sécurité ASP.NET Core Blazor côté serveur.

N’utilisez pas IHttpContextAccessor/HttpContext directement ou indirectement dans les composants Razor des applications Blazor côté serveur. Les applications Blazor s’exécutent en dehors du contexte de pipeline ASP.NET Core. Le HttpContext n’est pas garanti d’être disponible dans le IHttpContextAccessor, et HttpContext n’est pas garanti de conserver le contexte qui a démarré l’application Blazor.

L’approche recommandée pour passer l’état de la requête à l’application Blazor consiste à utiliser les paramètres de composant racine pendant le rendu initial de l’application. L’application peut également copier les données dans un service délimité dans l’événement de cycle de vie d’initialisation du composant racine pour une utilisation dans l’application. Pour plus d’informations, consultez Autres scénarios de sécurité ASP.NET Core Blazor côté serveur.

Un aspect essentiel de la sécurité de Blazor côté serveur réside dans le fait que l’utilisateur attaché à un circuit donné peut être mis à jour à un moment donné après l’établissement du circuit Blazor, mais que le IHttpContextAccessorn’est pas mis à jour. Pour plus d’informations sur la résolution de cette situation avec des services personnalisés, consultez Autres scénarios de sécurité ASP.NET Core Blazor côté serveur.

État partagé

Les applications Blazor côté serveur résident dans la mémoire du serveur, et plusieurs sessions d’application sont hébergées dans le même processus. Pour chaque session d’application, Blazor démarre un circuit avec sa propre étendue de conteneur d’injection de dépendances, de sorte que les services délimités sont uniques par session Blazor.

Avertissement

Nous ne recommandons pas que les applications sur le même serveur partagent un état à l’aide des services singleton, sauf si des précautions extrêmes sont prises, car cela peut introduire des vulnérabilités de sécurité, comme des fuites d’état utilisateur entre les circuits.

Vous pouvez utiliser des services singleton avec état dans les applications Blazor si elles sont spécifiquement conçues pour cela. Par exemple, l’utilisation d’un cache de mémoire singleton est acceptable, car un cache de mémoire nécessite une clé pour accéder à une entrée donnée. En supposant que les utilisateurs ne contrôlent pas les clés de cache utilisées avec le cache, l’état stocké dans le cache ne fuit pas entre les circuits.

Pour obtenir des conseils généraux sur la gestion de l’état, consultez Gestion de l’état BlazorASP.NET Core.

Authentification Blazor côté client

Dans les applications Blazor côté client, les vérifications d’authentification côté client peuvent être contournées, car le code côté client peut être modifié par des utilisateurs. Cela vaut également pour toutes les technologies d’application côté client, y compris les infrastructures d’application monopage JavaScript et les applications natives pour n’importe quel système d’exploitation.

Ajoutez ce qui suit :

Pour gérer l’authentification, l’utilisation du service AuthenticationStateProvider intégré ou personnalisé est traitée dans les sections suivantes.

Pour plus d’informations, consultez Sécuriser ASP.NET Core Blazor WebAssembly.

Service AuthenticationStateProvider

AuthenticationStateProvider est le service sous-jacent utilisé par le composant AuthorizeView et les services d’authentification en cascade pour obtenir l’état d’authentification d’un utilisateur.

AuthenticationStateProvider est le service sous-jacent utilisé par le composant AuthorizeView et le composant CascadingAuthenticationState pour obtenir l’état d’authentification d’un utilisateur.

Vous n’utilisez généralement pas AuthenticationStateProvider directement. Utilisez le composant AuthorizeView ou les approches Task<AuthenticationState> décrites plus loin dans cet article. Le principal inconvénient de l’utilisation directe de AuthenticationStateProvider est que le composant n’est pas automatiquement averti en cas de modifications de données d’état de l’authentification sous-jacente.

Le service AuthenticationStateProvider peut fournir les données ClaimsPrincipal de l’utilisateur actuel, comme indiqué dans l’exemple suivant.

ClaimsPrincipalData.razor:

@page "/claims-principle-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

@if (claims.Count() > 0)
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@surname</p>

@code {
    private string? authMessage;
    private string? surname;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

Dans l'exemple précédent :

  • ClaimsPrincipal.Claims retourne les revendications de l’utilisateur (claims) pour affichage dans l’interface utilisateur.
  • Ligne qui obtient les appels ClaimsPrincipal.FindAll du nom de l’utilisateur (surname) avec un prédicat pour filtrer les revendications de l’utilisateur.
@page "/claims-principle-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

@if (claims.Count() > 0)
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@surname</p>

@code {
    private string? authMessage;
    private string? surname;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

Si user.Identity.IsAuthenticated est true et parce que l’utilisateur est ClaimsPrincipal, les revendications peuvent être énumérées et l’appartenance aux rôles évaluée.

Pour plus d’informations sur l’injection de dépendances (DI) et les services, consultez Injection de dépendances ASP.NET Core Blazor et Injection de dépendances dans ASP.NET Core. Pour plus d’informations sur l’implémentation d’un AuthenticationStateProvider personnalisé dans des applications Blazor côté serveur, consultez Sécuriser des applications Blazor ASP.NET Core côté serveur.

Exposer l’état d’authentification comme un paramètre en cascade

Si les données d’état d’authentification sont requises pour la logique procédurale, par exemple lors d’une action déclenchée par l’utilisateur, obtenez les données d’état d’authentification en définissant un paramètre en cascade de type Task<AuthenticationState>, comme le montre l’exemple suivant.

CascadeAuthState.razor:

@page "/cascade-auth-state"

<h1>Cascade Auth State</h1>

<p>@authMessage</p>

@code {
    private string authMessage = "The user is NOT authenticated.";

    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user?.Identity is not null && user.Identity.IsAuthenticated)
            {
                authMessage = $"{user.Identity.Name} is authenticated.";
            }
        }
    }
}
@page "/cascade-auth-state"

<h1>Cascade Auth State</h1>

<p>@authMessage</p>

@code {
    private string authMessage = "The user is NOT authenticated.";

    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user?.Identity is not null && user.Identity.IsAuthenticated)
            {
                authMessage = $"{user.Identity.Name} is authenticated.";
            }
        }
    }
}

Si user.Identity.IsAuthenticated est true, les revendications peuvent être énumérées et l’appartenance aux rôles évaluée.

Configurez le Task<AuthenticationState>paramètre en cascade en utilisant le AuthorizeRouteView et les services d’état d’authentification en cascade.

Lorsque vous créez une application Blazor à partir de l’un des modèles de projet Blazor dont l’authentification est activée, l’application contient le AuthorizeRouteView et l’appel à AddCascadingAuthenticationState présentés dans l’exemple suivant. Une application Blazor côté client inclut également les inscriptions de service requises. Des informations supplémentaires sont présentées dans la section Personnaliser le contenu non autorisé avec le composant Routeur.

<Router ...>
    <Found ...>
        <AuthorizeRouteView RouteData="routeData" 
            DefaultLayout="typeof(Layout.MainLayout)" />
        ...
    </Found>
</Router>

Dans le fichier Program, inscrivez les services d’état d’authentification en cascade :

builder.Services.AddCascadingAuthenticationState();

Configurez Task<AuthenticationState>, un paramètre en cascade, à l’aide des composants AuthorizeRouteView etCascadingAuthenticationState.

Lorsque vous créez une application Blazor à partir de l’un des modèles de projet Blazor dont l’authentification est activée, l’application contient les composants AuthorizeRouteView etCascadingAuthenticationState présentés dans l’exemple suivant. Une application Blazor côté client inclut également les inscriptions de service requises. Des informations supplémentaires sont présentées dans la section Personnaliser le contenu non autorisé avec le composant Routeur.

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView RouteData="routeData" 
                DefaultLayout="typeof(MainLayout)" />
            ...
        </Found>
    </Router>
</CascadingAuthenticationState>

Remarque

Depuis le lancement d’ASP.NET Core 5.0.1 et pour les éventuelles versions 5.x supplémentaires, le composant Router comprend le paramètre PreferExactMatches, qui est défini sur @true. Pour plus d’informations, consultez Migrer de ASP.NET Core 3.1 vers 5.0.

Dans une application Blazor côté client, ajoutez des services pour les options et l’autorisation au fichier Program :

builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();

Dans une application Blazor côté serveur, les services pour les options et l’autorisation sont déjà présents. Par conséquent, aucune étape supplémentaire n’est nécessaire.

Autorisation

Une fois qu’un utilisateur est authentifié, les règles d’autorisation sont appliquées pour contrôler ce que l’utilisateur peut faire.

L’accès est généralement accordé ou refusé selon les conditions suivantes :

  • Un utilisateur est authentifié (connecté).
  • Un utilisateur appartient à un rôle.
  • Un utilisateur a une revendication.
  • Une stratégie est satisfaite.

Tous ces concepts sont les mêmes que dans une application ASP.NET Core MVC ou Razor Pages. Pour plus d’informations sur la sécurité d’ASP.NET Core, consultez les articles sous Sécurité ASP.NET Core et Identity.

AuthorizeView (composant)

Le composant AuthorizeView affiche de manière sélective le contenu d’interface utilisateur en fonction de l’autorisation dont dispose l’utilisateur. Cette approche est utile lorsque vous devez uniquement afficher les données de l’utilisateur et que vous n’avez pas besoin d’utiliser l’identité de l’utilisateur dans la logique procédurale.

Le composant expose une variable context de type AuthenticationState (@context dans la syntaxe Razor), que vous pouvez utiliser pour accéder aux informations relatives à l’utilisateur connecté :

<AuthorizeView>
    <p>Hello, @context.User.Identity?.Name!</p>
</AuthorizeView>

Si l’utilisateur n’est pas autorisé, vous pouvez également fournir un contenu différent à afficher en combinant les paramètres Authorized et NotAuthorized :

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
        <p><button @onclick="SecureMethod">Authorized Only Button</button></p>
    </Authorized>
    <NotAuthorized>
        <p>You're not authorized.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    private void SecureMethod() { ... }
}

Un gestionnaire d’événements par défaut pour un élément autorisé, comme la méthode SecureMethod pour l’élément <button> dans l’exemple précédent, ne peut être appelé que par un utilisateur autorisé.

Les composants Razor des applications web Blazor n’affichent jamais de contenu <NotAuthorized> lorsque l’autorisation échoue côté serveur pendant le rendu côté serveur statique (SSR statique). Le pipeline ASP.NET Core côté serveur traite l’autorisation sur le serveur. Utilisez des techniques côté serveur pour traiter les requêtes non autorisées. Pour plus d’informations, consultez Modes de rendu ASP.NET Core Blazor.

Avertissement

Le balisage côté client et les méthodes associées à un AuthorizeView sont uniquement protégés contre l’affichage et l’exécution dans l’interface utilisateur affichée dans les applications Blazor côté client. Afin de protéger un contenu autorisé et des méthodes sécurisées dans Blazor côté client, le contenu est généralement fourni par un appel d’API web sécurisé et autorisé à une API de serveur et n’est jamais stocké dans l’application. Pour plus d’informations, consultez Appeler une API web à partir d’une application ASP.NET Core Blazor et scénarios de sécurité supplémentaires Blazor WebAssembly ASP.NET Core.

Le contenu de Authorized et de NotAuthorized peut inclure des éléments arbitraires, comme d’autres composants interactifs.

Les conditions d’autorisation, comme les rôles ou les stratégies qui contrôlent les options d’interface utilisateur ou d’accès, sont traitées dans la section Autorisation.

Si les conditions d’autorisation ne sont pas spécifiées, AuthorizeView utilise une stratégie par défaut :

  • Les utilisateurs authentifiés (connectés) sont autorisés.
  • Les utilisateurs non authentifiés (déconnectés) ne sont pas autorisés.

Le composant AuthorizeView peut être utilisé dans le composant NavMenu (Shared/NavMenu.razor) pour afficher un composant NavLink (NavLink), mais notez que cette approche supprime uniquement l’élément de liste de la sortie affichée. Elle n’empêche pas l’utilisateur d’accéder au composant. Implémentez l’autorisation séparément dans le composant de destination.

Autorisation en fonction du rôle et de la stratégie

Le composant AuthorizeView prend en charge l’autorisation basée sur le rôle et basée sur les stratégies.

Pour l’autorisation en fonction du rôle, utilisez le paramètre Roles. Dans l’exemple suivant, l’utilisateur doit avoir une revendication de rôle pour les rôles Admin ou Superuser :

<AuthorizeView Roles="Admin, Superuser">
    <p>You have an 'Admin' or 'Superuser' role claim.</p>
</AuthorizeView>

Pour exiger qu’un utilisateur ait à la fois des revendications de rôle Admin et Superuser, imbriquez AuthorizeView composants :

<AuthorizeView Roles="Admin">
    <p>User: @context.User</p>
    <p>You have the 'Admin' role claim.</p>
    <AuthorizeView Roles="Superuser" Context="innerContext">
        <p>User: @innerContext.User</p>
        <p>You have both 'Admin' and 'Superuser' role claims.</p>
    </AuthorizeView>
</AuthorizeView>

Le code précédent établit un Context pour le composant interne AuthorizeView afin d’éviter une collision de contexte AuthenticationState. Le contexte AuthenticationState est accessible dans l’extérieur AuthorizeView avec l’approche standard pour accéder au contexte (@context.User). Le contexte est accessible dans l’intérieur AuthorizeView avec le contexte nommé innerContext (@innerContext.User).

Pour plus d’informations, notamment des conseils de configuration, consultez Autorisation basée sur les rôles dans ASP.NET Core.

Pour l’autorisation basée sur une stratégie, utilisez le paramètre Policy avec une stratégie unique :

<AuthorizeView Policy="Over21">
    <p>You satisfy the 'Over21' policy.</p>
</AuthorizeView>

Pour gérer le cas où l’utilisateur doit satisfaire à une stratégie parmi d’autres, créez une stratégie qui confirme que l’utilisateur satisfait à d’autres stratégies.

Pour gérer le cas où l’utilisateur doit satisfaire plusieurs stratégies simultanément, suivez l’une des approches suivantes :

  • Créez une stratégie pour AuthorizeView qui confirme que l’utilisateur satisfait à plusieurs autres stratégies.

  • Imbriquez les stratégies dans plusieurs composants AuthorizeView :

    <AuthorizeView Policy="Over21">
        <AuthorizeView Policy="LivesInCalifornia">
            <p>You satisfy the 'Over21' and 'LivesInCalifornia' policies.</p>
        </AuthorizeView>
    </AuthorizeView>
    

L’autorisation basée sur les revendications est un cas spécial d’autorisation basée sur les stratégies. Par exemple, vous pouvez définir une stratégie qui impose aux utilisateurs d’avoir une certaine revendication. Pour plus d’informations, consultez Autorisation basée sur une stratégie dans ASP.NET Core.

Si ni Roles ni Policy n’est spécifié, AuthorizeView utilise la stratégie par défaut :

  • Les utilisateurs authentifiés (connectés) sont autorisés.
  • Les utilisateurs non authentifiés (déconnectés) ne sont pas autorisés.

Étant donné que les comparaisons de chaînes .NET respectent la casse par défaut, les noms de rôle et de stratégie correspondants respectent également la casse. Par exemple, Admin (A majuscule) n’est pas traité comme le même rôle que admin (a minuscule).

La casse Pascal est généralement utilisée pour les noms de rôles et de stratégie (par exemple, BillingAdministrator), mais son utilisation n’est pas une exigence stricte. Différents schémas de casse, tels que la case chameau, la casse kebab et la casse serpent, sont autorisés. L’utilisation d’espaces dans les noms de rôle et de stratégie est inhabituelle, mais autorisée par l’infrastructure. Par exemple, billing administrator est un format de rôle ou de nom de stratégie inhabituel dans les applications .NET, mais il s’agit d’un nom de rôle ou de stratégie valide.

Contenu affiché lors de l’authentification asynchrone

Blazor permet de déterminer l’état d’authentification de façon asynchrone. Le scénario principal de cette approche réside dans les applications Blazor côté client qui créent une requête d’authentification sur un point de terminaison externe.

Lorsque l’authentification est en cours, AuthorizeView n’affiche aucun contenu par défaut. Pour afficher le contenu lors de l’authentification, affectez le contenu au paramètre Authorizing :

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
    </Authorized>
    <Authorizing>
        <p>You can only see this content while authentication is in progress.</p>
    </Authorizing>
</AuthorizeView>

Cette approche n’est normalement pas applicable aux applications Blazor côté serveur. Les applications Blazor côté serveur connaissent l’état de l’authentification dès que l’état est établi. Un contenu Authorizing peut être fourni dans le composant d’une application AuthorizeView, mais le contenu n’est jamais affiché.

Attribut [Authorize]

L’[Authorize]attribut est disponible dans les composantsRazor :

@page "/"
@attribute [Authorize]

You can only see this if you're signed in.

Important

Utilisez uniquement [Authorize] sur des composants @page auxquels l’accès se fait via le routeur Blazor. L’autorisation est effectuée uniquement en tant qu’aspect du routage et pas pour les composants enfants rendus dans une page. Pour autoriser l’affichage d’éléments spécifiques dans une page, utilisez AuthorizeView à la place.

L’attribut [Authorize] prend aussi en charge l’autorisation basée sur les rôles ou sur une stratégie. Pour l’autorisation en fonction du rôle, utilisez le paramètre Roles :

@page "/"
@attribute [Authorize(Roles = "Admin, Superuser")]

<p>You can only see this if you're in the 'Admin' or 'Superuser' role.</p>

Pour l’autorisation en fonction des stratégies, utilisez le paramètre Policy :

@page "/"
@attribute [Authorize(Policy = "Over21")]

<p>You can only see this if you satisfy the 'Over21' policy.</p>

Si ni Roles ni Policy n’est spécifié, [Authorize] utilise la stratégie par défaut :

  • Les utilisateurs authentifiés (connectés) sont autorisés.
  • Les utilisateurs non authentifiés (déconnectés) ne sont pas autorisés.

Lorsque l’utilisateur n’est pas autorisé et si l’application ne personnalise pas le contenu non autorisé avec le composant Routeur, l’infrastructure affiche automatiquement le message de secours suivant :

Not authorized.

Autorisation des ressources

Pour autoriser des utilisateurs pour les ressources, transmettez les données de route de la requête au paramètre Resource de AuthorizeRouteView.

Dans le contenu Router.Found d’une route demandée :

<AuthorizeRouteView Resource="routeData" RouteData="routeData" 
    DefaultLayout="typeof(MainLayout)" />

Pour plus d’informations sur la façon dont les données d’état d’autorisation sont transmises et utilisées dans la logique procédurale, consultez la section Exposer l’état d’authentification sous la forme d’un paramètre en cascade.

Quand AuthorizeRouteView reçoit les données de route pour la ressource, les stratégies d’autorisation ont accès à RouteData.PageType et RouteData.RouteValues, ce qui permet à la logique personnalisée de prendre des décisions d’autorisation.

Dans l’exemple suivant, une stratégie EditUser est créée dans AuthorizationOptions pour la configuration du service d’autorisation de l’application (AddAuthorizationCore) avec la logique suivante :

  • Déterminer s’il existe une valeur de route avec la clé id. Si la clé existe, la valeur de route est stockée dans value.
  • Dans une variable nommée id, stocker value sous forme de chaîne ou définir une valeur de chaîne vide (string.Empty).
  • Si id n’est pas une chaîne vide, déclarer que la stratégie est satisfaite (retourner true) si la valeur de la chaîne commence par EMP. Sinon, déclarer que la stratégie échoue (retourner false).

Dans le fichier Program :

  • Ajouter des espaces de noms pour Microsoft.AspNetCore.Components et System.Linq :

    using Microsoft.AspNetCore.Components;
    using System.Linq;
    
  • Ajouter la stratégie :

    options.AddPolicy("EditUser", policy =>
        policy.RequireAssertion(context =>
        {
            if (context.Resource is RouteData rd)
            {
                var routeValue = rd.RouteValues.TryGetValue("id", out var value);
                var id = Convert.ToString(value, 
                    System.Globalization.CultureInfo.InvariantCulture) ?? string.Empty;
    
                if (!string.IsNullOrEmpty(id))
                {
                    return id.StartsWith("EMP", StringComparison.InvariantCulture);
                }
            }
    
            return false;
        })
    );
    

L’exemple précédent est une stratégie d’autorisation simplifiée à l’excès, simplement destinée à illustrer le concept à partir d’un exemple pratique. Pour plus d’informations sur la création et la configuration de stratégies d’autorisation, consultez Autorisation basée sur une stratégie dans ASP.NET Core.

Dans le composant EditUser suivant, la ressource au niveau de /users/{id}/edit possède un paramètre de route pour l’identificateur de l’utilisateur ({id}). Le composant utilise la stratégie d’autorisation EditUser précédente pour déterminer si la valeur de route de id commence par EMP. Si id commence par EMP, la stratégie aboutit et l’accès au composant est autorisé. Si id commence par une autre valeur que EMP ou si id est une chaîne vide, la stratégie échoue et le composant ne se charge pas.

EditUser.razor:

@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h1>Edit User</h1>

<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

@code {
    [Parameter]
    public string? Id { get; set; }
}
@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h1>Edit User</h1>

<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

@code {
    [Parameter]
    public string? Id { get; set; }
}

Personnaliser le contenu non autorisé avec le composant Router

Le composant Router, conjointement avec le composant AuthorizeRouteView, permet à l’application de spécifier du contenu personnalisé si :

  • L’utilisateur ne répond pas à une condition [Authorize] appliquée au composant. Le balisage de l’élément <NotAuthorized> est affiché. L’attribut [Authorize] est décrit dans la section Attribut [Authorize].
  • L’autorisation asynchrone est en cours, ce qui signifie généralement que le processus d’authentification de l’utilisateur est en cours. Le balisage de l’élément <Authorizing> est affiché.

Important

Les fonctionnalités de routeur Blazor qui affichent du contenu <NotAuthorized> et <NotFound> ne sont pas opérationnelles pendant le rendu côté serveur statique (SSR statique), car le traitement des requêtes est entièrement géré par le traitement des requêtes du pipeline intergiciel ASP.NET Core et les composants Razor ne sont pas du tout rendus pour les requêtes non autorisées ou incorrectes. Utilisez des techniques côté serveur pour traiter les requêtes non autorisées et incorrectes pendant le rendu côté serveur statique. Pour plus d’informations, consultez Modes de rendu ASP.NET Core Blazor.

<Router ...>
    <Found ...>
        <AuthorizeRouteView ...>
            <NotAuthorized>
                ...
            </NotAuthorized>
            <Authorizing>
                ...
            </Authorizing>
        </AuthorizeRouteView>
    </Found>
</Router>

Le contenu de Authorized et de NotAuthorized peut inclure des éléments arbitraires, comme d’autres composants interactifs.

Remarque

L’élément précédent nécessite l’inscription des services d’état d’authentification en cascade dans le fichier Program de l’application :

builder.Services.AddCascadingAuthenticationState();
<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView ...>
                <NotAuthorized>
                    ...
                </NotAuthorized>
                <Authorizing>
                    ...
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
    </Router>
</CascadingAuthenticationState>

Le contenu de NotFound, Authorized et NotAuthorized peut inclure des éléments arbitraires, comme d’autres composants interactifs.

Si le contenu NotAuthorized n’est pas spécifiée, le AuthorizeRouteView utilise le message de remplacement suivant :

Not authorized.

Une application créée à partir du modèle de projet Blazor WebAssembly dont l’authentification est activée comprend un composant RedirectToLogin qui est positionné dans le contenu <NotAuthorized> du composant Router. Lorsqu’un utilisateur n’est pas authentifié (context.User.Identity?.IsAuthenticated != true), le composant RedirectToLogin redirige le navigateur vers le point de terminaison authentication/login pour l’authentification. L’utilisateur est renvoyé à l’URL demandée après s’être authentifié auprès du fournisseur d’identité.

Logique procédurale

Si l’application est appelée à vérifier les règles d’autorisation dans le cadre de la logique procédurale, utilisez un paramètre en cascade de type Task<AuthenticationState> pour obtenir le ClaimsPrincipal de l’utilisateur. Task<AuthenticationState> peut être combiné avec d’autres services, comme IAuthorizationService, pour évaluer les stratégies.

Dans l’exemple suivant :

  • Le user.Identity.IsAuthenticated exécute le code pour les utilisateurs authentifiés (connectés).
  • Le user.IsInRole("admin") exécute le code pour les utilisateurs dans le rôle « Admin ».
  • Le (await AuthorizationService.AuthorizeAsync(user, "content-editor")).Succeeded exécute le code pour les utilisateurs respectant la stratégie « éditeur de contenu ».

Une application Blazor côté serveur inclut les espaces de noms appropriés par défaut lorsqu’elle est créée à partir du modèle de projet. Dans une application Blazor côté client, confirmez la présence des espaces de noms Microsoft.AspNetCore.Authorization et Microsoft.AspNetCore.Components.Authorization dans le composant ou dans le fichier de l’application _Imports.razor :

@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization

ProceduralLogic.razor:

@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService

<h1>Procedural Logic Example</h1>

<button @onclick="@DoSomething">Do something important</button>

@code {
    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    private async Task DoSomething()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user is not null)
            {
                if (user.Identity is not null && user.Identity.IsAuthenticated)
                {
                    // ...
                }

                if (user.IsInRole("Admin"))
                {
                    // ...
                }

                if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
                    .Succeeded)
                {
                    // ...
                }
            }
        }
    }
}
@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService

<h1>Procedural Logic Example</h1>

<button @onclick="@DoSomething">Do something important</button>

@code {
    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    private async Task DoSomething()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user is not null)
            {
                if (user.Identity is not null && user.Identity.IsAuthenticated)
                {
                    // ...
                }

                if (user.IsInRole("Admin"))
                {
                    // ...
                }

                if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
                    .Succeeded)
                {
                    // ...
                }
            }
        }
    }
}

Résoudre les erreurs

Erreurs courantes :

  • L’autorisation exige un paramètre en cascade de type Task<AuthenticationState>. Envisagez d’utiliser CascadingAuthenticationState pour le fournir.

  • La valeur null est reçue pour authenticationStateTask

Il est probable que le projet n’a pas été créé à l’aide d’un modèle Blazor côté serveur dont l’authentification est activée.

Dans .NET 7 ou versions antérieures, enveloppez un <CascadingAuthenticationState> dans certaines parties de l’arborescence de l’interface utilisateur, par exemple dans le routeur Blazor :

<CascadingAuthenticationState>
    <Router ...>
        ...
    </Router>
</CascadingAuthenticationState>

Dans .NET 8 ou versions ultérieures, n’utilisez pas le composant CascadingAuthenticationState :

- <CascadingAuthenticationState>
      <Router ...>
          ...
      </Router>
- </CascadingAuthenticationState>

Ajoutez à la place des services d’état d’authentification en cascade à la collection de services dans le fichier Program :

builder.Services.AddCascadingAuthenticationState();

Le composant CascadingAuthenticationState (.NET 7 ou versions antérieures) ou les services fournis par AddCascadingAuthenticationState (.NET 8 ou versions ultérieures) fournissent le paramètre en cascade Task<AuthenticationState> qui reçoit à son tour du service d’injection de dépendances AuthenticationStateProvider sous-jacent.

Informations d’identification personnelle (PII)

Microsoft utilise la définition RGPD pour les « données personnelles » (RGPD 4.1) lorsque la documentation traite des informations d’identification personnelle (PII).

L’IIP fait référence à toutes les informations relatives à une personne physique identifiée ou identifiable. Une personne physique identifiable est une personne qui peut être identifiée, directement ou indirectement, avec l’un des éléments suivants :

  • Nom
  • Numéro d’identification
  • Coordonnées d’emplacement
  • Identificateur en ligne
  • Autres facteurs spécifiques
    • Physique
    • Physiologiques
    • Génétique
    • Mental (psychologique)
    • Économique
    • Culturel
    • Identité sociale

Ressources supplémentaires