Modifier les Claims d'un utilisateur dans une application ASP.NET Core
Lorsqu'un utilisateur s'authentifie sur votre site Web (via une authentification Windows ou autre), il récupère un ensemble de Claims, qui correspondent aux informations sur son identité: son nom, ses rôles, etc. Il peut être intéressant de voir comment transformer ses informations pour en rajouter et/ou en supprimer.
Pour implémenter cette mécanique dans une application ASP.NET Core 2.1, il est nécessaire de créer une classe qui va implémenter l'interface IClaimsTransformation. Cette interface expose une méthode, TransformAsync, qui sera appelée automatique par le Framework une fois le processus d'authentification terminé. C'est donc le bon endroit pour récupérer les informations sur l'utilisateur courant et jouer avec ses Claims et renvoyer un nouvel objet de type ClaimsPrincipal correspondant à l'identité (modifiée) de l'utilisateur:
public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal) { var identity = ((ClaimsIdentity)principal.Identity); var claimsIdentity = new ClaimsIdentity(identity.Claims, "WindowsAuthentication", identity.NameClaimType, identity.RoleClaimType); // Get group name according to their SID var userRoles = identity.Claims .Where(c => c.Type == ClaimTypes.GroupSid) .Select(c => new System.Security.Principal.SecurityIdentifier(c.Value).Translate(typeof(System.Security.Principal.NTAccount)).ToString()); if (userRoles.Any(r => "MonSuperGroupAdAvecDesAdministrateurs")) { claimsIdentity.AddClaim(new Claim("Administrators", "Administrators")); } var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); return Task.FromResult(claimsPrincipal); }
Le code présenté ci-dessous permet de récupérer l'identité de l'utilisateur qui vient de s'authentifier puis de vérifier, dans ses Claims, s'il est membre d'un groupe Active Directory nommé "MonSuperGroupAdAvecDesAdministrateurs".
La particularité ici réside dans le fait que les Claims renvoyées pour les groupes AD (et certains groupes locaux) sont représentées sous forme de Security Identifier (SID) et non sous forme de chaînes de caractères (plus simple à manipuler): nous effectuons donc une petite opération de transformation pour obtenir le nom des SID (à partir de leur identifiant).
Autre point (important) à noter: au moment de la création de l'objet ClaimsIdentity, nous utilisons "WindowsAuthentication" pour le paramètre AuthenticationType. Pour bien faire, nous aurions dû récupérer le type d'authentification de l'utilisateur connecté pour le réutiliser:
var claimsIdentity = new ClaimsIdentity(identity.Claims, identity.AuthenticationType, identity.NameClaimType, identity.RoleClaimType);
Cependant, cette syntaxe provoque une exception (sur ASP.NET Core 2.1) lors de l'accès à la propriété AuthenticationType et le seul workaround pour le moment est de spécifier le type sous forme de chaîne de caractères (ce qui n'est pas dérangeant, dans le cas d'une authentification Windows).
Pour terminer, il ne reste qu'à enregistrer votre classe dans les services:
services.AddSingleton<IClaimsTransformation, ActivateDirectoryClaimsTransformer>();
Happy coding! :)
Commentaires