18-1 Claims et ClaimsFactory
Identity
fait usage du concept de Claims
pour gérer des propriétés supplémentaires associées à l'utilisateur.
Il faut voir le terme Claims
un peu comme quelque chose que l'utilisateur s'est approprié. La traduction la plus directe serait une revendication. Les claims permettent de décrire ce qu'un utilisateur est:
- Id
- Nom
- Prenom
- Courriel
- Role
- ...
Ces claims
se retrouvent dans le cookie contenant certains détails de l'utilisateur et qui est récupéré à chaque requête par le serveur.
Par défaut, seulement le nom d'utilisateur de l'usager (le courriel dans notre cas) se trouve dans la liste de Claims
.
Pour ajouter des Claims
, il faudra créer une classe héritant de UserClaimsPrincipalFactory
et réimplémenter la fonction responsable de générer les claims, soit GenerateClaimsAsync
.
Créer une classe UserClaimsPrincipalFactory
La classe UserClaimsPrincipalFactory
sera responsable de générer les Claims
.
Comme il s'agit d'une implémentation propre à la logique de notre application, nous la mettrons dans le projet Application
. Le meilleur endroit est cependant ouvert à interprétation.
- Créer un dossier
Claims
. Sous le projetApplication
, ajoutez un dossier nomméClaims
. - Créer la classe. Sous le nouveau dossier
Snowfall.Application/Claims
, ajoutez une classe nomméeApplicationClaimsPrincipalFactory.cs
- Code de base. Pour débuter, vous pouvez mettre ceci dans la classe:
Snowfall.Application/Claims/ApplicationClaimsPrincipalFactory.cs
using System.Security.Claims;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using Snowfall.Domain.Models;
namespace Snowfall.Application.Claims;
/// <summary>
/// Permets de générer les attributs de l'utilisateur (Claims) étant accessibles sans faire de requête
/// à la BD. Ces claims sont donc stockés dans un cookie, par exemple (en mode rendu serveur), et récupérés
/// par le serveur à chaque requête.
/// </summary>
public class ApplicationClaimsPrincipalFactory : UserClaimsPrincipalFactory<ApplicationUser, ApplicationRole>
{
public ApplicationClaimsPrincipalFactory(
UserManager<ApplicationUser> userManager,
RoleManager<ApplicationRole> roleManager,
IOptions<IdentityOptions> options)
: base(userManager, roleManager, options)
{
}
/// <summary>
/// Génère les claims propres à l'application. Cette méthode 'override' celle de
/// UserClaimsPrincipalFactory. C'est pourquoi on appel base.GenerateClaimsAsync()
/// dans un premier temps.
/// </summary>
/// <param name="user"></param>
/// <returns></returns>
protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
{
ClaimsIdentity claims = await base.GenerateClaimsAsync(user);
return claims;
}
}
public class ApplicationClaimsPrincipalFactory
crée une classe qui hérite deUserClaimsPrincipalFactory
, soit la classe de .NET Core responsable de générer lesclaims
.protected override async Task<ClaimsIdentity> GenerateClaimsAsync
réimplémente la fonction responsable de générer les claims pour un utilisateurClaimsIdentity claims = await base.GenerateClaimsAsync(user);
pour conserver le comportement de base de la fonction, on peut appeler la même fonction que nous sommes en train de réimplémenter, mais surbase
, soit la classe parent
Ajouter des Claims
(attributs de l'utilisateur)
On peut ensuite ajouter diff érents attributs à la liste de Claims
, via AddClaim
de la façon suivante.
protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
{
ClaimsIdentity claims = await base.GenerateClaimsAsync(user);
claims.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Id!));
claims.AddClaim(new Claim(ClaimTypes.GivenName, user.Prenom));
claims.AddClaim(new Claim(ClaimTypes.Surname, user.Nom));
claims.AddClaim(new Claim("NomComplet", $"{user.Prenom} {user.Nom}"));
return claims;
}
Certains types prédéfinis sont disponibles, comme ClaimTypes.NameIdentifier
ou encore ClaimTypes.GivenName
, mais on peut aussi leur donner un nom personnalisé comme dans l'exemple "NomComplet"
.
Au fond, le premier paramètre est seulement un string
, qu'il s'agisse d'un d'un claim prédéfini ou nom.
Ainsi, dans notre cas, on ajoute les claims suivants:
NameIdentifier
le ID de l'utilisateurGivenName
le prénom de l'utilisateurSurname
le nom de l'utilisateurNomComplet
le nom complet de l'utilisateur