Loupe

OpenIdConnect : ajouter un claim à votre Principal une fois le token JWT validé

Lorsque vous mettez une authentification via OpenId Connect (en utilisant OpenIddict comme dans un de mes précédents articles), vous ne contrôlez pas vraiment les informations contenues dans votre token et qui seront insufflées dans l'identité de votre utilisateur. Dans cet article, nous verrons comment ajouter des informations au Principal une fois le token Jwt validé. 

 

La première chose à faire consiste à ajouter un gestionnaire d'événement à l'événement OnTokenValidated , pour renseigner les événements relatifs à l'authentification par Bearer Jwt.

Cela se passe dans la méthode AddJwtBearer :

services
 .AddAuthentication()
 .AddJwtBearer(
  options =>
  {
    options.Events = new JwtBearerEvents
    {
      OnTokenValidated = ExtraTokenValidationAsync
    };
  });

Vous pouvez alors lire votre token dont vous avez la garantie qu'il est valide et ajouter des informations au Principal créé par cette authentification par token. Le contexte passé en paramètre vous permet en outre d'accéder au système d'injection de dépendances, pour obtenir un DbContext par exemple. Ici, on récupère un identifiant tiré du token, puis on cherche l'utilisateur correspondant en base pour ajouter un claim à notre Principal. Comme cet événement est exécuté à chaque appel de l'API, il est intéressant de mettre en place du cache pour éviter de faire une requête en base à chaque fois.

private readonly Dictionary<string, ClaimsIdentity> 
    _userInformationCache
      = new Dictionary<string, ClaimsIdentity>();

private async Task 
  ExtraTokenValidationAsync(TokenValidatedContext context)
{
  if (context?.Principal == null)
  {
    return;
  }
  // lecture d'un claim tiré du token jwt
  var userId = context.Principal.FindFirst("idAuthent");
  if (string.IsNullOrEmpty(userId?.Value))
  {
    return;
  }
  if (!_userInformationCache
      .TryGetValue(userId.Value, out var appIdentity))
  {
    var dbContext = context.HttpContext.RequestServices
                        .GetRequiredService<TDbContext>();
    var upperCaseUserName = userId.Value.ToUpper();
    var userInDbId = await dbContext.Users
      .Where(u => u.IdAuthent == idAuthent)
      .Select(u => new long?(u.Valeur)).FirstOrDefaultAsync();
    if (userInDbId == null)
    {
      return;
    }
    // ajout d'un claim spécifique à notre application
    var claims = new List<Claim>
    {
      new Claim("MonClaimÀMoi", userInDbId.Value.ToString())
    };
    appIdentity = new ClaimsIdentity(claims);
    _userInformationCache[userId.Value] = appIdentity;
  }
  context.Principal.AddIdentity(appIdentity);
}

Happy coding :)

Pour aller plus loin.

Photo de profil

Ces billets pourraient aussi vous intéresser

Vous nous direz ?!

Commentaires

comments powered by Disqus