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.
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.
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. Ce paramètre est configuré dans le fichier Program.cs du projet Identity.API
, comme le montre 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 est configuré dans le Program.cs du projet Identity.API
en appelant la méthode AddIdentityServer
, comme le montre l'exemple de code suivant tiré de l'application de référence eShop :
builder.Services.AddIdentityServer(options =>
{
options.Authentication.CookieLifetime = TimeSpan.FromHours(2);
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
// TODO: Remove this line in production.
options.KeyManagement.Enabled = false;
})
.AddInMemoryIdentityResources(Config.GetResources())
.AddInMemoryApiScopes(Config.GetApiScopes())
.AddInMemoryApiResources(Config.GetApis())
.AddInMemoryClients(Config.GetClients(builder.Configuration))
.AddAspNetIdentity<ApplicationUser>()
// TODO: Not recommended for production - you need to store your key material somewhere secure
.AddDeveloperSigningCredential();
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 MAUI OpenId Client",
AllowedGrantTypes = GrantTypes.Code,
//Used to retrieve the access token on the back channel.
ClientSecrets =
{
new Secret("secret".Sha256())
},
RedirectUris = { configuration["MauiCallback"] },
RequireConsent = false,
RequirePkce = true,
PostLogoutRedirectUris = { $"{configuration["MauiCallback"]}/Account/Redirecting" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess,
"orders",
"basket",
"mobileshoppingagg",
"webhooks"
},
//Allow requesting refresh tokens for long lived API access
AllowOfflineAccess = true,
AllowAccessTokensViaBrowser = true,
AlwaysIncludeUserClaimsInIdToken = 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.
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.
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.
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.
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.