Partager via


Authentification et autorisation

Conseil

Ce contenu est un extrait du livre électronique Modèles d’application d’entreprise avec .NET MAUI, disponible dans la .documentation .NET ou en tant que PDF téléchargeable gratuitement qui peut être lu hors connexion.

Miniature de la couverture du livre électronique Modèles d’application d’entreprise avec .NET MAUI.

L’authentification consiste à obtenir des informations d’identification comme le nom et le mot de passe d’un utilisateur et à valider ces informations d’identification auprès d’une autorité. L’entité qui a envoyé les informations d’identification est considérée comme une identité authentifiée si les informations d’identification sont valides. Une fois qu’une identité a été établie, un processus d’autorisation détermine si cette identité a accès à une ressource donnée.

Il existe de nombreuses approches pour intégrer l’authentification et l’autorisation dans une application .NET MAUI qui communique avec une application web ASP.NET, notamment en utilisant ASP.NET Core Identity, des fournisseurs d’authentification externes comme Microsoft, Google, Facebook ou Twitter, et un intergiciel d’authentification. L’application multiplateforme eShop effectue le processus d’authentification et d’autorisation avec un microservice d’identité conteneurisé qui utilise IdentityServer. L’application demande des jetons de sécurité à IdentityServer pour authentifier un utilisateur ou accéder à une ressource. Pour qu’IdentityServer émette des jetons pour le compte d’un utilisateur, l’utilisateur doit se connecter à IdentityServer. Toutefois, IdentityServer ne fournit pas d’interface utilisateur ou de base de données pour l’authentification. Par conséquent, dans l’application de référence eShop, ASP.NET Core Identity est utilisé à cet effet.

Authentification

L’authentification est requise lorsqu’une application doit connaître l’identité de l’utilisateur actuel. Le mécanisme principal d’identification des utilisateurs d’ASP.NET Core est le système d’appartenance ASP.NET Core Identity, qui stocke les informations utilisateur dans une banque de données configurée par le développeur. En règle générale, ce magasin de données est un magasin EntityFramework, bien que des magasins personnalisés ou des packages tiers puissent être utilisés pour stocker des informations d’identité dans le stockage Azure, DocumentDB ou d’autres emplacements.

Pour les scénarios d’authentification qui utilisent un magasin de données utilisateur local et qui conservent l’identité entre les requêtes au moyen de cookies (comme c’est généralement le cas avec les applications web ASP.NET), ASP.NET Core Identity est une solution convenable. En revanche, dans d’autres scénarios, il n’est pas toujours commun de conserver et de transmettre les données au moyen de cookies. Par exemple, une application web ASP.NET Core qui expose des points de terminaison RESTful accessibles à partir d’une application doit généralement utiliser l’authentification par jeton du porteur, car les cookies ne peuvent pas être utilisés dans ce scénario. Toutefois, les jetons du porteur peuvent facilement être récupérés et inclus dans l’en-tête d’autorisation des requêtes web effectuées à partir de l’application.

Émission de jetons de porteur à l’aide d’IdentityServer

IdentityServer est un framework OpenID Connect et OAuth 2.0 open source pour ASP.NET Core, qui peut être utilisé pour de nombreux scénarios d’authentification et d’autorisation, notamment l’émission de jetons de sécurité pour les utilisateurs locaux ASP.NET Core Identity.

Remarque

OpenID Connect et OAuth 2.0 sont très similaires, tout en ayant des responsabilités différentes.

OpenID Connect est une couche d’authentification basée sur le protocole OAuth 2.0. OAuth 2 est un protocole qui permet aux applications de demander des jetons d’accès à un service de jetons de sécurité et de les utiliser pour communiquer avec les API. Cette délégation réduit la complexité des applications clientes et des API, car l’authentification et l’autorisation peuvent être centralisées.

OpenID Connect et OAuth 2.0 combinent les deux préoccupations de sécurité fondamentales de l’authentification et de l’accès à l’API, et IdentityServer est une implémentation de ces protocoles.

Dans les applications qui utilisent la communication directe de client à microservice, comme l’application de référence eShop, un microservice d’authentification dédié agissant en tant que service de jeton de sécurité (STS) peut être utilisé pour authentifier les utilisateurs, comme illustré dans le diagramme suivant. Pour plus d’informations sur la communication directe de client à microservice, consultez Microservices.

Authentification par un microservice d’authentification dédié.

L’application multiplateforme eShop communique avec le microservice d’identité, qui utilise IdentityServer pour effectuer l’authentification et le contrôle d’accès pour les API. Par conséquent, l’application multiplateforme demande des jetons à IdentityServer, soit pour authentifier un utilisateur, soit pour accéder à une ressource :

  • L’authentification des utilisateurs avec IdentityServer est réalisée par l’application multiplateforme demandant un jeton d’identité, représentant le résultat d’un processus d’authentification. Au minimum, il contient un identificateur pour l’utilisateur et des informations sur la façon et le moment où l’utilisateur est authentifié. Il peut également inclure des données d’identité supplémentaires.
  • L’accès à une ressource avec IdentityServer est obtenu par l’application multiplateforme qui demande un jeton d’accès, qui autorise l’accès à une ressource API. Les clients demandent des jetons d’accès et les transfèrent à l’API. Les jetons d’accès contiennent des informations sur le client et l’utilisateur, le cas échéant. Les API utilisent ensuite ces informations pour autoriser l’accès à leurs données.

Notes

Un client doit être inscrit auprès d’IdentityServer avant de pouvoir demander des jetons. Pour plus d’informations sur l’ajout de clients, consultez Définition de clients.

Ajout d’IdentityServer à une application web

Pour qu’une application web ASP.NET Core utilise IdentityServer, elle doit être ajoutée à la solution Visual Studio de l’application web. Pour plus d’informations, consultez Configuration et vue d’ensemble dans la documentation IdentityServer. Une fois IdentityServer inclus dans la solution Visual Studio de l’application web, il doit être ajouté à son pipeline de traitement des requêtes HTTP pour traiter les requêtes aux points de terminaison OpenID Connect et OAuth 2.0. Cette opération est configurée dans le Program.cs du projet Identity.API, comme illustré dans l’exemple de code suivant :


...

app.UseIdentityServer();

L’ordre est important dans le pipeline de traitement des requêtes HTTP de l’application web. Par conséquent, IdentityServer doit être ajouté au pipeline avant l’infrastructure d’interface utilisateur qui implémente l’écran de connexion.

Configuration d’IdentityServer

IdentityServer doit être configuré dans la méthode ConfigureServices de la classe Startup de l’application web en appelant la méthode services.AddIdentityServer, comme illustré dans l’exemple de code suivant de l’application de référence eShop :

public void ConfigureServices(IServiceCollection services)
{
    services
        .AddIdentityServer(x => x.IssuerUri = "null")
        .AddSigningCredential(Certificate.Get())
        .AddAspNetIdentity<ApplicationUser>()
        .AddConfigurationStore(builder =>
            builder.UseSqlServer(connectionString, options =>
                options.MigrationsAssembly(migrationsAssembly)))
        .AddOperationalStore(builder =>
            builder.UseSqlServer(connectionString, options =>
                options.MigrationsAssembly(migrationsAssembly)))
        .Services.AddTransient<IProfileService, ProfileService>();
}

Après avoir appelé la méthode services.AddIdentityServer, des API Fluent supplémentaires sont appelées pour configurer les éléments suivants :

  • Informations d’identification utilisées pour la signature.
  • Ressources d’API et d’identité auxquelles les utilisateurs peuvent demander l’accès.
  • Les clients appelés à se connecter pour demander des jetons.
  • Identité ASP.NET Core.

Conseil

Chargez dynamiquement la configuration IdentityServer. Les API d’IdentityServer permettent de configurer IdentityServer à partir d’une liste en mémoire d’objets de configuration. Dans l’application de référence eShop, ces collections en mémoire sont codées en dur dans l’application. Toutefois, dans les scénarios de production, elles peuvent être chargées dynamiquement à partir d’un fichier de configuration ou d’une base de données.

Pour plus d’informations sur la configuration d’IdentityServer pour utiliser ASP.NET Core Identity, consultez Utilisation d’ASP.NET Core Identity dans la documentation IdentityServer.

Configuration des ressources d’API

Lors de la configuration des ressources d’API, la méthode AddInMemoryApiResources attend une collection de IEnumerable<ApiResource>. L’exemple de code suivant montre la méthode GetApis qui fournit cette collection dans l’application de référence eShop :

public static IEnumerable<ApiResource> GetApis()
{
    return new List<ApiResource>
    {
        new ApiScope("orders", "Orders Service"),
        new ApiScope("basket", "Basket Service"),
        new ApiScope("webhooks", "Webhooks registration Service"),
    };
}

Cette méthode spécifie qu’IdentityServer doit protéger les API de commandes et de panier. Par conséquent, des jetons d’accès gérés par IdentityServer seront requis lors des appels à ces API. Pour plus d’informations sur le type ApiResource, consultez Ressource d’API dans la documentation IdentityServer.

Configuration des ressources d’identité

Lors de la configuration des ressources d’identité, la méthode AddInMemoryIdentityResources attend une collection de IEnumerable<IdentityResource>. Les ressources d’identité sont des données comme l’ID utilisateur, le nom ou l’adresse e-mail. Chaque ressource d’identité a un nom unique, et des types de revendications arbitraires peuvent lui être attribués ; ces types seront inclus dans le jeton d’identité de l’utilisateur. L’exemple de code suivant montre la méthode GetResources qui fournit cette collection dans l’application de référence eShop :

public static IEnumerable<IdentityResource> GetResources()
{
    return new List<IdentityResource>
    {
        new IdentityResources.OpenId(),
        new IdentityResources.Profile()
    };
}

La spécification OpenID Connect spécifie certaines ressources d’identité standard. La condition minimale est que la prise en charge soit fournie pour l’émission d’un ID unique pour les utilisateurs. Pour ce faire, exposez la ressource d’identité IdentityResources.OpenId.

Notes

La classe IdentityResources prend en charge toutes les étendues définies dans la spécification OpenID Connect (openid, e-mail, profil, téléphone et adresse).

IdentityServer prend également en charge la définition de ressources d’identité personnalisées. Pour plus d’informations, consultez Définition de ressources d’identité personnalisées dans la documentation IdentityServer. Pour plus d’informations sur le type IdentityResource, consultez Identity Resource dans la documentation IdentityServer.

Configuration des clients

Les clients sont des applications qui peuvent demander des jetons à IdentityServer. En règle générale, les paramètres suivants doivent être définis au minimum pour chaque client :

  • ID client unique.
  • Interactions autorisées avec le service de jeton (type d’autorisation).
  • Emplacement où les jetons d’identité et d’accès sont envoyés (URI de redirection).
  • Liste des ressources auxquelles le client est autorisé à accéder (étendues).

Lors de la configuration des clients, la méthode AddInMemoryClients attend une collection de IEnumerable<Client>. L’exemple de code suivant montre la configuration de l’application multiplateforme eShop dans la méthode GetClients qui fournit cette collection dans l’application de référence eShop :

public static IEnumerable<Client> GetClients(Dictionary<string,string> clientsUrl)
{
    return new List<Client>
    {
        // Omitted for brevity
        new Client
        {
            ClientId = "maui",
            ClientName = "eShop .NET MAUI OpenId Client",
            AllowedGrantTypes = GrantTypes.Hybrid,
            ClientSecrets =
            {
                new Secret("secret".Sha256())
            },
            RedirectUris = { clientsUrl["maui"] },
            RequireConsent = false,
            RequirePkce = true,
            PostLogoutRedirectUris = { $"{clientsUrl["maui"]}/Account/Redirecting" },
            AllowedCorsOrigins = { "http://eshopmaui" },
            AllowedScopes = new List<string>
            {
                IdentityServerConstants.StandardScopes.OpenId,
                IdentityServerConstants.StandardScopes.Profile,
                IdentityServerConstants.StandardScopes.OfflineAccess,
                "orders",
                "basket"
            },
            AllowOfflineAccess = true,
            AllowAccessTokensViaBrowser = true,
            AccessTokenLifetime = 60 * 60 * 2, // 2 hours
            IdentityTokenLifetime = 60 * 60 * 2 // 2 hours
        }
    };
}

Cette configuration spécifie les données pour les propriétés suivantes :

Propriété Description
ClientId ID unique du client.
ClientName Nom d’affichage du client, qui est utilisé pour la journalisation et l’écran de consentement.
AllowedGrantTypes Spécifie comment un client souhaite interagir avec IdentityServer. Pour plus d’informations, consultez Configuration du flux d’authentification.
ClientSecrets Spécifie les informations d’identification de la clé secrète client utilisées lors de la demande de jetons à partir du point de terminaison du jeton.
RedirectUris Spécifie les URI autorisés auxquels retourner des jetons ou des codes d’autorisation.
RequireConsent Spécifie si un écran de consentement est requis.
RequirePkce Spécifie si les clients utilisant un code d’autorisation doivent envoyer une clé de preuve.
PostLogoutRedirectUris Spécifie les URI de destination autorisées pour la redirection après la déconnexion.
AllowedCorsOrigins Spécifie l’origine du client afin qu’IdentityServer puisse autoriser les appels inter-origines à partir de l’origine.
AllowedScopes Spécifie les ressources auxquelles le client a accès. Par défaut, un client n’a accès à aucune ressource.
AllowOfflineAccess Spécifie si le client peut demander des jetons d’actualisation.
AllowAccessTokensViaBrowser Spécifie si le client peut recevoir des jetons d’accès à partir d’une fenêtre de navigateur.
AlwaysIncludeUserClaimsInIdToken Spécifie que les revendications utilisateur seront toujours ajoutées au jeton de l’ID. Par défaut, celles-ci doivent être récupérées à l’aide du point de terminaison userinfo.
AccessTokenLifetime Spécifie la durée de vie du jeton d’accès en secondes.
IdentityTokenLifetime Spécifie la durée de vie du jeton d’identité en secondes.

Configuration du flux d’authentification

Le flux d’authentification entre un client et IdentityServer peut être configuré en spécifiant les types d’octroi dans la propriété Client.AllowedGrantTypes. Les spécifications OpenID Connect et OAuth 2.0 définissent plusieurs flux d’authentification, notamment :

Flux d'authentification Description
Implicite Ce flux est optimisé pour les applications basées sur un navigateur, et doit être utilisé soit pour l’authentification utilisateur uniquement, soit pour les demandes d’authentification et de jeton d’accès. Tous les jetons sont transmis via le navigateur et, par conséquent, les fonctionnalités avancées comme les jetons d’actualisation ne sont pas autorisées.
Code d’autorisation. Ce flux permet de récupérer des jetons sur un canal d’arrière-plan, par opposition au canal frontal du navigateur, tout en prenant en charge l’authentification du client.
Hybride Ce flux est une combinaison des types d’octroi de code implicite et d’autorisation. Le jeton d’identité est transmis via le canal du navigateur et contient la réponse du protocole signé et d’autres artefacts, comme le code d’autorisation. Après avoir validé la réponse, le canal d’arrière-plan doit être utilisé pour récupérer le jeton d’accès et d’actualisation.

Conseil

Envisagez d’utiliser le flux d’authentification hybride. Le flux d’authentification hybride atténue un certain nombre d’attaques qui s’appliquent au canal du navigateur. Il s’agit du flux recommandé pour les applications natives qui souhaitent récupérer des jetons d’accès (et éventuellement actualiser des jetons).

Pour plus d’informations sur les flux d’authentification, consultez Types d’autorisation dans la documentation IdentityServer.

Exécution de l’authentification

Pour qu’IdentityServer émette des jetons pour le compte d’un utilisateur, l’utilisateur doit se connecter à IdentityServer. Toutefois, IdentityServer ne fournit pas d’interface utilisateur ou de base de données pour l’authentification. Par conséquent, dans l’application de référence eShop, ASP.NET Core Identity est utilisé à cet effet.

L’application multiplateforme eShop s’authentifie auprès d’IdentityServer avec le flux d’authentification hybride, comme illustré dans le diagramme ci-dessous.

Vue d’ensemble du processus de connexion.

Une demande de connexion est envoyée à <base endpoint>:5105/connect/authorize. Une fois l’authentification réussie, IdentityServer retourne une réponse d’authentification contenant un code d’autorisation et un jeton d’identité. Le code d’autorisation est envoyé à <base endpoint>:5105/connect/token, qui répond avec des jetons d’accès, d’identité et d’actualisation.

L’application multiplateforme eShop se déconnecte d’IdentityServer en envoyant une requête à <base endpoint>:5105/connect/endsession avec des paramètres supplémentaires. Après la déconnexion, IdentityServer répond en envoyant un URI de redirection post-déconnexion à l’application multiplateforme. Le diagramme ci-dessous illustre ce processus.

Vue d’ensemble générale du processus de déconnexion.

Dans l’application multiplateforme eShop, la communication avec IdentityServer est effectuée par la classe IdentityService, qui implémente l’interface IIdentityService. Cette interface spécifie que la classe d’implémentation doit fournir les méthodes SignInAsync, SignOutAsync, GetUserInfoAsync et GetAuthTokenAsync.

Connexion

Lorsque l’utilisateur appuie sur le bouton LOGIN sur LoginView, le SignInCommand dans la classe LoginViewModel est exécuté, ce qui exécute à son tour la méthode SignInAsync. L’exemple de code suivant illustre cette méthode :

[RelayCommand]
private async Task SignInAsync()
{
    await IsBusyFor(
        async () =>
        {
            var loginSuccess = await _appEnvironmentService.IdentityService.SignInAsync();

            if (loginSuccess)
            {
                await NavigationService.NavigateToAsync("//Main/Catalog");
            }
        });
}

Cette méthode appelle la méthode SignInAsync dans la classe IdentityService, comme illustré dans l’exemple de code suivant :

public async Task<bool> SignInAsync()
{
    var response = await GetClient().LoginAsync(new LoginRequest()).ConfigureAwait(false);

    if (response.IsError)
    {
        return false;
    }

    await _settingsService
        .SetUserTokenAsync(
            new UserToken
            {
                AccessToken = response.AccessToken,
                IdToken = response.IdentityToken,
                RefreshToken = response.RefreshToken,
                ExpiresAt = response.AccessTokenExpiration
            })
        .ConfigureAwait(false);

    return !response.IsError;
}

IdentityService utilise l’OidcClient fourni avec le package NuGet IdentityModel.OidcClient. Ce client affiche la vue web de l’authentification à l’utilisateur dans l’application et capture le résultat de l’authentification. Le client se connecte à l’URI du point de terminaison d’autorisation d’IdentityServer avec les paramètres requis. Le point de terminaison d’autorisation se trouve à /connect/authorize sur le port 5105 du point de terminaison de base exposé en tant que paramètre utilisateur. Pour plus d’informations sur les paramètres utilisateur, consultez Gestion de la configuration.

Remarque

La surface d’attaque de l’application multiplateforme eShop est réduite en implémentant l’extension Proof Key for Code Exchange (PKCE) dans OAuth. PKCE protège le code d’autorisation contre l’utilisation en cas d’interception. Pour ce faire, le client génère un vérificateur de secrets, dont un hachage est passé dans la demande d’autorisation et qui est présenté sans hachage lors de l’utilisation du code d’autorisation. Pour plus d’informations sur PKCE, consultez Proof Key for Code Exchange by OAuth Public Clients sur le site web Internet Engineering Task Force.

Page de connexion affichée par la WebView.

Si le point de terminaison de jeton reçoit des informations d’authentification, un code d’autorisation et un vérificateur de secret PKCE valides, il répond avec un jeton d’accès, un jeton d’identité et un jeton d’actualisation. Le jeton d’accès (qui autorise l’accès aux ressources d’API) et le jeton d’identité sont stockés en tant que paramètres d’application, et la navigation sur les pages est effectuée. Par conséquent, l’effet global dans l’application multiplateforme eShop est le suivant : à condition que les utilisateurs puissent s’authentifier avec IdentityServer, ils sont redirigés vers l’itinéraire //Main/Catalog, qui est un TabbedPage qui affiche CatalogView comme onglet sélectionné.

Pour plus d’informations sur la navigation de page, consultez Navigation. Pour plus d’informations sur la façon dont la navigation WebView entraîne l’exécution d’une méthode de modèle d’affichage, consultez Appel de la navigation à l’aide de comportements. Pour plus d’informations sur les paramètres de l’application, consultez Gestion de la configuration.

Remarque

L’eShop autorise également une connexion fictive lorsque l’application est configurée pour utiliser des services fictifs dans le SettingsView. Dans ce mode, l’application ne communique pas avec IdentityServer, mais autorise l’utilisateur à se connecter à l’aide de toutes informations d’identification.

Déconnexion

Lorsque l’utilisateur appuie sur le bouton LOG OUT sur ProfileView, le LogoutCommand dans la classe ProfileViewModel est exécuté, ce qui exécute la méthode LogoutAsync. Cette méthode procède à la navigation dans la page LoginView, en passant un jeu de paramètres de requête Logout à true.

Ce paramètre est évalué dans la méthode ApplyQueryAttributes. Si le paramètre Logout est présent avec une valeur true, la méthode PerformLogoutAsync de la classe LoginViewModel est exécutée, tel qu’illustré dans l’exemple de code suivant :

private async Task PerformLogoutAsync()
{
    await _appEnvironmentService.IdentityService.SignOutAsync();

    _settingsService.UseFakeLocation = false;

    UserName.Value = string.Empty;
    Password.Value = string.Empty;
}

Cette méthode appelle la méthode SignOutAsync dans la classe IdentityService, qui appelle l’OidcClient pour mettre fin à la session de l’utilisateur et efface les jetons d’utilisateur enregistrés. Pour plus d’informations sur les paramètres d’application, consultez Gestion de la configuration. L’exemple de code suivant montre la méthode SignOutAsync :

public async Task<bool> SignOutAsync()
{
    var response = await GetClient().LogoutAsync(new LogoutRequest()).ConfigureAwait(false);

    if (response.IsError)
    {
        return false;
    }

    await _settingsService.SetUserTokenAsync(default);

    return !response.IsError;
}

Cette méthode utilise l’OidcClient pour appeler l’URI dans le point de terminaison de session de fin d’IdentityServer avec les paramètres requis. Le point de terminaison de session de fin se trouve à /connect/endsession sur le port 5105 du point de terminaison de base exposé en tant que paramètre utilisateur. Une fois que l’utilisateur s’est correctement déconnecté, LoginView est présenté à l’utilisateur et toutes les informations utilisateur enregistrées sont effacées.

Pour plus d’informations sur la navigation de page, consultez Navigation. Pour plus d’informations sur la façon dont la navigation WebView entraîne l’exécution d’une méthode de modèle d’affichage, consultez Appel de la navigation à l’aide de comportements. Pour plus d’informations sur les paramètres de l’application, consultez Gestion de la configuration.

Remarque

L’eShop autorise également une déconnexion fictive lorsque l’application est configurée pour utiliser des services fictifs dans le SettingsView. Dans ce mode, l’application ne communique pas avec IdentityServer et efface les jetons stockés des paramètres de l’application.

Autorisation

Après l’authentification, les API web ASP.NET Core doivent souvent autoriser l’accès, ce qui permet à un service de rendre les API accessibles à certains utilisateurs authentifiés, mais pas à tous.

La restriction de l’accès à un itinéraire ASP.NET Core peut être obtenue en appliquant un attribut Authorize à un contrôleur ou à une action, ce qui limite l’accès au contrôleur ou à l’action aux utilisateurs authentifiés, comme illustré dans l’exemple de code suivant :

[Authorize]
public sealed class BasketController : Controller
{
    // Omitted for brevity
}

Si un utilisateur non autorisé tente d’accéder à un contrôleur ou une action marquée avec l’attribut Authorize, l’infrastructure d’API retourne un code d’état HTTP 401 (unauthorized).

Notes

Des paramètres peuvent être spécifiés sur l’attribut Authorize pour restreindre une API à des utilisateurs spécifiques. Pour plus d’informations, consultez la Documentation ASP.NET Core : Autorisation.

IdentityServer peut être intégré au workflow d’autorisation afin que les jetons d’accès fournissent l’autorisation de contrôle. Cette approche est illustrée dans le diagramme ci-dessous.

Autorisation par jeton d’accès.

L’application multiplateforme eShop communique avec le microservice d’identité et demande un jeton d’accès dans le cadre du processus d’authentification. Le jeton d’accès est ensuite transféré aux API exposées par les microservices de classement et de panier dans le cadre des demandes d’accès. Les jetons d’accès contiennent des informations sur le client et l’utilisateur. Les API utilisent ensuite ces informations pour autoriser l’accès à leurs données. Pour plus d’informations sur la configuration d’IdentityServer pour protéger les API, consultez Configuration des ressources d’API.

Configuration d’IdentityServer pour effectuer l’autorisation

Pour effectuer l’autorisation avec IdentityServer, son intergiciel d’autorisation doit être ajouté au pipeline de requêtes HTTP de l’application web. L’intergiciel est ajouté dans la méthode d’extension AddDefaultAuthentication, qui est appelée à partir de la méthode AddApplicationServices dans la classe Program et illustrée dans l’exemple de code suivant de l’application de référence eShop :

public static IServiceCollection AddDefaultAuthentication(this IHostApplicationBuilder builder)
{
    var services = builder.Services;
    var configuration = builder.Configuration;

    var identitySection = configuration.GetSection("Identity");

    if (!identitySection.Exists())
    {
        // No identity section, so no authentication
        return services;
    }

    // prevent from mapping "sub" claim to nameidentifier.
    JsonWebTokenHandler.DefaultInboundClaimTypeMap.Remove("sub");

    services.AddAuthentication().AddJwtBearer(options =>
    {
        var identityUrl = identitySection.GetRequiredValue("Url");
        var audience = identitySection.GetRequiredValue("Audience");

        options.Authority = identityUrl;
        options.RequireHttpsMetadata = false;
        options.Audience = audience;
        options.TokenValidationParameters.ValidIssuers = [identityUrl];
        options.TokenValidationParameters.ValidateAudience = false;
    });

    services.AddAuthorization();

    return services;
}

Cette méthode garantit que l’API n’est accessible qu’avec un jeton d’accès valide. L’intergiciel valide le jeton entrant pour s’assurer qu’il est envoyé à partir d’un émetteur approuvé, et vérifie que le jeton est valide pour être utilisé avec l’API qui le reçoit. Par conséquent, l’accès au contrôleur de commande ou de panier retourne un code d’état HTTP 401 (unauthorized), indiquant qu’un jeton d’accès est nécessaire.

Envoi de demandes d’accès aux API

Lorsque vous effectuez des requêtes auprès des microservices de commande et de panier, le jeton d’accès obtenu auprès d’IdentityServer pendant le processus d’authentification doit être inclus dans la requête, comme indiqué dans l’exemple de code suivant :

public async Task CreateOrderAsync(Models.Orders.Order newOrder)
{
    var authToken = await _identityService.GetAuthTokenAsync().ConfigureAwait(false);

    if (string.IsNullOrEmpty(authToken))
    {
        return;
    }

    var uri = $"{UriHelper.CombineUri(_settingsService.GatewayOrdersEndpointBase, ApiUrlBase)}?api-version=1.0";

    var success = await _requestProvider.PostAsync(uri, newOrder, authToken, "x-requestid").ConfigureAwait(false);
}

Le jeton d’accès est stocké avec l’implémentation IIdentityService et peut être récupéré à l’aide de la méthode GetAuthTokenAsync.

De même, le jeton d’accès doit être inclus lors de l’envoi de données à une API protégée par IdentityServer, comme indiqué dans l’exemple de code suivant :

public async Task ClearBasketAsync()
{
    var authToken = await _identityService.GetAuthTokenAsync().ConfigureAwait(false);

    if (string.IsNullOrEmpty(authToken))
    {
        return;
    }

    await GetBasketClient().DeleteBasketAsync(new DeleteBasketRequest(), CreateAuthenticationHeaders(authToken))
        .ConfigureAwait(false);
}

Le jeton d’accès est récupéré à partir d’IIdentityService et inclus dans l’appel à la méthode ClearBasketAsync dans la classe BasketService.

La classe RequestProvider dans l’application multiplateforme eShop utilise la classe HttpClient pour effectuer des requêtes aux API RESTful exposées par l’application de référence eShop. Lorsque vous effectuez des requêtes pour les API de commande et de panier, qui nécessitent une autorisation, un jeton d’accès valide doit être inclus avec la demande. Pour ce faire, ajoutez le jeton d’accès aux en-têtes de l’instance HttpClient, comme illustré dans l’exemple de code suivant :

httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);

La propriété DefaultRequestHeaders de la classe HttpClient expose les en-têtes envoyés avec chaque requête, et le jeton d’accès est ajouté à l’en-tête Authorization précédé de la chaîne Bearer. Lorsque la requête est envoyée à une API RESTful, la valeur de l’en-tête Authorization est extraite et validée pour s’assurer qu’elle est envoyée à partir d’un émetteur approuvé et utilisée pour déterminer si l’utilisateur a l’autorisation d’appeler l’API qui la reçoit.

Pour plus d’informations sur la façon dont l’application multiplateforme eShop effectue des requêtes web, consultez Accès aux données distantes.

Résumé

Il existe de nombreuses approches pour intégrer l’authentification et l’autorisation dans une application .NET MAUI qui communique avec une application web ASP.NET. L’application multiplateforme eShop effectue le processus d’authentification et d’autorisation avec un microservice d’identité conteneurisé qui utilise IdentityServer. IdentityServer est un framework OpenID Connect et OAuth 2.0 open source pour ASP.NET Core qui s’intègre à ASP.NET Core Identity pour effectuer l’authentification par jeton de porteur.

L’application multiplateforme demande des jetons de sécurité à IdentityServer pour authentifier un utilisateur ou accéder à une ressource. Lors de l’accès à une ressource, un jeton d’accès doit être inclus dans la requête aux API qui nécessitent une autorisation. L’intergiciel d’IdentityServer valide les jetons d’accès entrants pour s’assurer qu’ils sont envoyés à partir d’un émetteur approuvé et qu’ils sont valides pour être utilisés avec l’API qui les reçoit.