Ajoutez l’authentification à votre application .NET Core (Blazor WASM)
- La démonstration suivante est construite sur .NET Core 8.0 et Blorc.OpenIdConnect.
- Les projets d'exemple .NET Core sont disponibles dans le répertoire GitHub.
Prérequis
- Un compte Logto Cloud ou un Logto auto-hébergé.
- Une application monopage Logto créée.
Installation
Ajoutez le package NuGet à votre projet :
dotnet add package Blorc.OpenIdConnect
Intégration
Ajouter des références de script
Inclure Blorc.Core/injector.js dans le fichier index.html :
<head>
<!-- ... -->
<script src="_content/Blorc.Core/injector.js"></script>
<!-- ... -->
</head>
Enregistrer les services
Ajoutez le code suivant au fichier Program.cs :
using Blorc.OpenIdConnect;
using Blorc.Services;
builder.Services.AddBlorcCore();
builder.Services.AddAuthorizationCore();
builder.Services.AddBlorcOpenIdConnect(
options =>
{
builder.Configuration.Bind("IdentityServer", options);
});
var webAssemblyHost = builder.Build();
await webAssemblyHost
.ConfigureDocumentAsync(async documentService =>
{
await documentService.InjectBlorcCoreJsAsync();
await documentService.InjectOpenIdConnectAsync();
});
await webAssemblyHost.RunAsync();
Il n'est pas nécessaire d'utiliser le package Microsoft.AspNetCore.Components.WebAssembly.Authentication. Le package Blorc.OpenIdConnect prendra en charge le processus d'authentification (Authentication).
Configurer les URIs de redirection
Avant d’entrer dans les détails, voici un aperçu rapide de l’expérience utilisateur finale. Le processus de connexion peut être simplifié comme suit :
- Votre application lance la méthode de connexion.
- L’utilisateur est redirigé vers la page de connexion Logto. Pour les applications natives, le navigateur système est ouvert.
- L’utilisateur se connecte et est redirigé vers votre application (configurée comme l’URI de redirection).
Concernant la connexion basée sur la redirection
- Ce processus d'authentification (Authentication) suit le protocole OpenID Connect (OIDC), et Logto applique des mesures de sécurité strictes pour protéger la connexion utilisateur.
- Si vous avez plusieurs applications, vous pouvez utiliser le même fournisseur d’identité (Logto). Une fois que l'utilisateur se connecte à une application, Logto complétera automatiquement le processus de connexion lorsque l'utilisateur accède à une autre application.
Pour en savoir plus sur la logique et les avantages de la connexion basée sur la redirection, consultez Expérience de connexion Logto expliquée.
Dans les extraits de code suivants, nous supposons que votre application fonctionne sur http://localhost:3000/.
Configurer les URIs de redirection
Passez à la page des détails de l'application de Logto Console. Ajoutez une URI de redirection http://localhost:3000/callback.
Tout comme pour la connexion, les utilisateurs doivent être redirigés vers Logto pour se déconnecter de la session partagée. Une fois terminé, il serait idéal de rediriger l'utilisateur vers votre site web. Par exemple, ajoutez http://localhost:3000/ comme section d'URI de redirection après déconnexion.
Ensuite, cliquez sur "Enregistrer" pour sauvegarder les modifications.
Configurer l'application
Ajoutez le code suivant au fichier appsettings.json :
{
// ...
IdentityServer: {
Authority: 'https://<your-logto-endpoint>/oidc',
ClientId: '<your-logto-app-id>',
PostLogoutRedirectUri: 'http://localhost:3000/',
RedirectUri: 'http://localhost:3000/callback',
ResponseType: 'code',
Scope: 'openid profile', // Ajoutez plus de portées (Portées) si nécessaire
},
}
N'oubliez pas d'ajouter le RedirectUri et le PostLogoutRedirectUri à la liste des URIs de redirection autorisées dans les paramètres de l'application Logto. Ce sont tous deux l'URL de votre application WASM.
Ajouter le composant AuthorizeView
Dans les pages Razor qui nécessitent une authentification (Authentication), ajoutez le composant AuthorizeView. Supposons que ce soit la page Home.razor :
@using Microsoft.AspNetCore.Components.Authorization
@page "/"
<AuthorizeView>
<Authorized>
@* Vue connectée *@
<button @onclick="OnLogoutButtonClickAsync">
Se déconnecter
</button>
</Authorized>
<NotAuthorized>
@* Vue non authentifiée *@
<button @onclick="OnLoginButtonClickAsync">
Se connecter
</button>
</NotAuthorized>
</AuthorizeView>
Configurer l'authentification (Authentication)
Dans le fichier Home.razor.cs (créez-le s'il n'existe pas), ajoutez le code suivant :
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using Blorc.OpenIdConnect;
using Microsoft.AspNetCore.Components.Authorization;
[Authorize]
public partial class Home : ComponentBase
{
[Inject]
public required IUserManager UserManager { get; set; }
public User<Profile>? User { get; set; }
[CascadingParameter]
protected Task<AuthenticationState>? AuthenticationStateTask { get; set; }
protected override async Task OnInitializedAsync()
{
User = await UserManager.GetUserAsync<User<Profile>>(AuthenticationStateTask!);
}
private async Task OnLoginButtonClickAsync(MouseEventArgs obj)
{
await UserManager.SignInRedirectAsync();
}
private async Task OnLogoutButtonClickAsync(MouseEventArgs obj)
{
await UserManager.SignOutRedirectAsync();
}
}
Une fois que l'utilisateur est authentifié, la propriété User sera remplie avec les informations de l'utilisateur.
Point de contrôle : Testez votre application
Maintenant, vous pouvez tester votre application :
- Exécutez votre application, vous verrez le bouton de connexion.
- Cliquez sur le bouton de connexion, le SDK initiera le processus de connexion et vous redirigera vers la page de connexion Logto.
- Après vous être connecté, vous serez redirigé vers votre application et verrez le bouton de déconnexion.
- Cliquez sur le bouton de déconnexion pour effacer le stockage des jetons et vous déconnecter.
Obtenir des informations sur l'utilisateur
Afficher les informations utilisateur
Voici quelques exemples de la façon d'afficher les informations utilisateur dans la page Home.razor :
<AuthorizeView>
<Authorized>
@* Vue connectée *@
@* ... *@
<p>Vous êtes connecté en tant que @(@User?.Profile?.Name ?? "(nom inconnu)").</p>
</Authorized>
@* ... *@
</AuthorizeView>
Pour plus de propriétés et de revendications, consultez les classes User et Profile dans le package Blorc.OpenIdConnect.
Demander des revendications supplémentaires
Il se peut que certaines informations utilisateur soient manquantes dans l'objet retourné par User. Cela est dû au fait que OAuth 2.0 et OpenID Connect (OIDC) sont conçus pour suivre le principe du moindre privilège (PoLP), et Logto est construit sur ces normes.
Par défaut, des revendications limitées sont retournées. Si vous avez besoin de plus d'informations, vous pouvez demander des portées supplémentaires pour accéder à plus de revendications.
Une "revendication" est une affirmation faite à propos d'un sujet ; une "portée" est un groupe de revendications. Dans le cas actuel, une revendication est une information sur l'utilisateur.
Voici un exemple non normatif de la relation portée - revendication :
La revendication "sub" signifie "sujet", qui est l'identifiant unique de l'utilisateur (c'est-à-dire l'ID utilisateur).
Le SDK Logto demandera toujours trois portées : openid, profile, et offline_access.
Pour demander des portées supplémentaires, vous pouvez ajouter des portées valides à la propriété IdentityServer.Scope dans le fichier appsettings.json.
{
// ...
"IdentityServer": {
// ...
"Scope": "openid profile email phone"
}
}
Revendications nécessitant une requête réseau
Pour éviter de surcharger l'objet utilisateur, certaines revendications nécessitent des requêtes réseau pour être récupérées. Par exemple, la revendication custom_data n'est pas incluse dans l'objet utilisateur même si elle est demandée dans les portées. Pour récupérer ces revendications, vous pouvez définir la propriété IdentityServer.LoadUserInfo sur true dans le fichier appsettings.json.
Par exemple, pour récupérer l'adresse e-mail de l'utilisateur et les données personnalisées, vous pouvez utiliser la configuration suivante :
{
// ...
"IdentityServer": {
// ...
"Scope": "openid profile email custom_data",
"LoadUserInfo": true
}
}
Portées et revendications
Logto utilise les conventions OIDC sur les portées (scopes) et revendications (claims) pour définir les portées et revendications permettant de récupérer les informations utilisateur depuis le jeton d’identifiant (ID token) et le point de terminaison OIDC userinfo. Les termes "portée (Scope)" et "revendication (Claim)" proviennent des spécifications OAuth 2.0 et OpenID Connect (OIDC).
Pour les revendications OIDC standard, leur inclusion dans le jeton d’identifiant est strictement déterminée par les portées demandées. Les revendications étendues (telles que custom_data et organizations) peuvent être configurées en plus pour apparaître dans le jeton d’identifiant via les paramètres Jeton d’identifiant personnalisé.
Voici la liste des portées prises en charge et les revendications correspondantes :
Portées OIDC standard
openid (par défaut)
| Nom de la revendication | Type | Description |
|---|---|---|
| sub | string | L'identifiant unique de l'utilisateur |
profile (par défaut)
| Nom de la revendication | Type | Description |
|---|---|---|
| name | string | Le nom complet de l'utilisateur |
| username | string | Le nom d'utilisateur de l'utilisateur |
| picture | string | URL de la photo de profil de l'utilisateur final. Cette URL DOIT référencer un fichier image (par exemple, un fichier PNG, JPEG ou GIF), plutôt qu'une page Web contenant une image. Notez que cette URL DOIT référencer spécifiquement une photo de profil de l'utilisateur final adaptée à l'affichage lors de la description de l'utilisateur final, et non une photo quelconque prise par l'utilisateur final. |
| created_at | number | Date de création de l'utilisateur final. Le temps est représenté par le nombre de millisecondes écoulées depuis l'époque Unix (1970-01-01T00:00:00Z). |
| updated_at | number | Date de la dernière mise à jour des informations de l'utilisateur final. Le temps est représenté par le nombre de millisecondes écoulées depuis l'époque Unix (1970-01-01T00:00:00Z). |
D'autres revendications standard telles que family_name, given_name, middle_name, nickname, preferred_username, profile, website, gender, birthdate, zoneinfo et locale seront également incluses dans la portée profile sans avoir besoin de demander l'endpoint userinfo. Une différence par rapport aux revendications ci-dessus est que ces revendications ne seront retournées que si leurs valeurs ne sont pas vides, tandis que les revendications ci-dessus retourneront null si les valeurs sont vides.
Contrairement aux revendications standard, les revendications created_at et updated_at utilisent les millisecondes au lieu des secondes.
email
| Nom de la revendication | Type | Description |
|---|---|---|
string | L'adresse e-mail de l'utilisateur | |
| email_verified | boolean | Si l'adresse e-mail a été vérifiée |
phone
| Nom de la revendication | Type | Description |
|---|---|---|
| phone_number | string | Le numéro de téléphone de l'utilisateur |
| phone_number_verified | boolean | Si le numéro de téléphone a été vérifié |
address
Veuillez vous référer à la spécification OpenID Connect Core 1.0 pour les détails de la revendication d'adresse.
Les portées marquées (par défaut) sont toujours demandées par le SDK Logto. Les revendications sous les portées OIDC standard sont toujours incluses dans le jeton d’identifiant lorsque la portée correspondante est demandée — elles ne peuvent pas être désactivées.
Portées étendues
Les portées suivantes sont étendues par Logto et retourneront des revendications via l’endpoint userinfo. Ces revendications peuvent également être configurées pour être incluses directement dans le jeton d’identifiant via Console > JWT personnalisé. Voir Jeton d’identifiant personnalisé pour plus de détails.
custom_data
| Nom de la revendication | Type | Description | Inclus dans le jeton d’identifiant par défaut |
|---|---|---|---|
| custom_data | object | Les données personnalisées de l'utilisateur |
identities
| Nom de la revendication | Type | Description | Inclus dans le jeton d’identifiant par défaut |
|---|---|---|---|
| identities | object | Les identités liées de l'utilisateur | |
| sso_identities | array | Les identités SSO liées de l'utilisateur |
roles
| Nom de la revendication | Type | Description | Inclus dans le jeton d’identifiant par défaut |
|---|---|---|---|
| roles | string[] | Les rôles de l'utilisateur | ✅ |
urn:logto:scope:organizations
| Nom de la revendication | Type | Description | Inclus dans le jeton d’identifiant par défaut |
|---|---|---|---|
| organizations | string[] | Les identifiants d’organisation auxquels l'utilisateur appartient | ✅ |
| organization_data | object[] | Les données d’organisation auxquelles l'utilisateur appartient |
Ces revendications d’organisation peuvent également être récupérées via l’endpoint userinfo lors de l’utilisation d’un jeton opaque. Cependant, les jetons opaques ne peuvent pas être utilisés comme jetons d’organisation pour accéder à des ressources spécifiques à une organisation. Voir Jeton opaque et organisations pour plus de détails.
urn:logto:scope:organization_roles
| Nom de la revendication | Type | Description | Inclus dans le jeton d’identifiant par défaut |
|---|---|---|---|
| organization_roles | string[] | Les rôles d’organisation auxquels l'utilisateur appartient au format <organization_id>:<role_name> | ✅ |
Ressources API
Nous vous recommandons de lire d'abord 🔐 Contrôle d’accès basé sur les rôles (RBAC) pour comprendre les concepts de base de Logto RBAC et comment configurer correctement les ressources API.
Par défaut, lorsque vous accédez à User?.AccessToken, vous obtenez un jeton opaque (Opaque token) qui a une longueur courte et n'est pas un JWT (JSON Web Token). Ce jeton est utilisé pour accéder à l'endpoint userinfo.
Ajouter une ressource API à la configuration
Afin d'obtenir un JWT pouvant être utilisé pour accéder à une ressource API (API resource) définie dans Logto, ajoutez les paramètres suivants au fichier appsettings.json (en prenant https://my-api-resource comme exemple) :
{
// ...
"IdentityServer": {
// ...
"Scope": "openid profile email <your-api-scopes>", // Ajoutez ici vos portées d’API
"Resource": "https://my-api-resource",
"ExtraTokenParams": {
"resource": "https://my-api-resource" // Assurez-vous que la clé "resource" est en minuscules
}
}
}
La propriété Resource est utilisée pour ajouter la ressource API (API resource) à la requête d'authentification. La propriété ExtraTokenParams est utilisée pour ajouter la ressource API à la requête de jeton (token request). Puisque Logto est conforme à la RFC 8707 pour les ressources API, les deux propriétés sont requises.
Puisque WebAssembly est une application côté client, la requête de jeton (token request) ne sera envoyée au serveur qu'une seule fois. De ce fait, LoadUserInfo est en conflit avec la récupération du jeton d’accès (Access token) pour les ressources API.
Utiliser le jeton d’accès
Une fois l'utilisateur authentifié, vous pouvez accéder à la ressource API (API resource) en utilisant la propriété User?.AccessToken. Par exemple, vous pouvez utiliser le HttpClient pour accéder à la ressource API :
using Blorc.OpenIdConnect;
builder.Services
.AddHttpClient("MyApiResource", client =>
{
client.BaseAddress = new Uri("https://my-api-resource");
})
.AddAccessToken(); // Ajoute le jeton d’accès (Access token) à l’en-tête de la requête