web-dev-qa-db-fra.com

Comment décoder le jeton JWT?

Je ne comprends pas comment cette bibliothèque fonctionne. Pourrais-tu m'aider s'il te plait ?

Voici mon code simple:

public void TestJwtSecurityTokenHandler()
    {
        var stream =
            "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJJU1MiLCJzY29wZSI6Imh0dHBzOi8vbGFyaW0uZG5zY2UuZG91YW5lL2NpZWxzZXJ2aWNlL3dzIiwiYXVkIjoiaHR0cHM6Ly9kb3VhbmUuZmluYW5jZXMuZ291di5mci9vYXV0aDIvdjEiLCJpYXQiOiJcL0RhdGUoMTQ2ODM2MjU5Mzc4NClcLyJ9";
        var handler = new JwtSecurityTokenHandler();

        var jsonToken = handler.ReadToken(stream);
    }

C'est l'erreur:

La chaîne doit être au format JSON compact, de la forme suivante: Base64UrlEncodedHeader.Base64UrlEndcodedPayload.OPTIONAL, Base64UrlEncodedSignature '.

Si vous copiez le flux dans site Web jwt.io , cela fonctionne très bien :)

66
Cooxkie

J'ai trouvé la solution, j'ai juste oublié de jeter le résultat:

var stream ="[encoded jwt]";  
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(stream);
var tokenS = handler.ReadToken(tokenJwtReponse.access_token) as JwtSecurityToken;

Je peux obtenir des réclamations en utilisant:

var jti = tokenS.Claims.First(claim => claim.Type == "jti").Value;
102
Cooxkie

new JwtSecurityTokenHandler().ReadToken("") retournera un SecurityToken

new JwtSecurityTokenHandler().ReadJwtToken("") retournera un JwtSecurityToken

Si vous ne faites que modifier la méthode que vous utilisez, vous pouvez éviter la conversion dans la réponse ci-dessus.

15
dpix

Vous avez besoin de la chaîne secrète utilisée pour générer le jeton de chiffrement. Ce code fonctionne pour moi:

protected string GetName(string token)
    {
        string secret = "this is a string used for encrypt and decrypt token"; 
        var key = Encoding.ASCII.GetBytes(secret);
        var handler = new JwtSecurityTokenHandler();
        var validations = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(key),
            ValidateIssuer = false,
            ValidateAudience = false
        };
        var claims = handler.ValidateToken(token, validations, out var tokenSecure);
        return claims.Identity.Name;
    }
9
Pato Milán

En utilisant les packages .net core jwt, les revendications sont disponibles:

[Route("api/[controller]")]
[ApiController]
[Authorize(Policy = "Bearer")]
public class AbstractController: ControllerBase
{
    protected string UserId()
    {
        var principal = HttpContext.User;
        if (principal?.Claims != null)
        {
            foreach (var claim in principal.Claims)
            {
               log.Debug($"CLAIM TYPE: {claim.Type}; CLAIM VALUE: {claim.Value}");
            }

        }
        return principal?.Claims?.SingleOrDefault(p => p.Type == "username")?.Value;
    }
}
4

Étendre sur cooxkie answer, et dpix answer, lorsque vous lisez un jeton jwt (tel qu'un access_token reçu de AD FS), vous pouvez fusionner les revendications dans le jeton jwt. avec les revendications de "context.AuthenticationTicket.Identity" qui pourraient ne pas avoir le même ensemble de revendications que le jeton jwt.

Pour illustrer, dans un flux de codes d'authentification utilisant OpenID Connect, une fois qu'un utilisateur est authentifié, vous pouvez gérer l'événement SecurityTokenValidated qui vous fournit un contexte d'authentification. Vous pouvez ensuite l'utiliser pour lire access_token en tant que jwt token, vous pouvez alors "fusionner" les jetons qui se trouvent dans le paramètre access_token avec la liste standard des revendications reçues dans le cadre de l'identité de l'utilisateur:

    private Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage,OpenIdConnectAuthenticationOptions> context)
    {
        //get the current user identity
        ClaimsIdentity claimsIdentity = (ClaimsIdentity)context.AuthenticationTicket.Identity;

        /*read access token from the current context*/
        string access_token = context.ProtocolMessage.AccessToken;

        JwtSecurityTokenHandler hand = new JwtSecurityTokenHandler();
        //read the token as recommended by Coxkie and dpix
        var tokenS = hand.ReadJwtToken(access_token);
        //here, you read the claims from the access token which might have 
        //additional claims needed by your application
        foreach (var claim in tokenS.Claims)
        {
            if (!claimsIdentity.HasClaim(claim.Type, claim.Value))
                claimsIdentity.AddClaim(claim);
        }

        return Task.FromResult(0);
    }
2
TamerDev
  var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var claims = new[]
                {
                    new Claim(JwtRegisteredClaimNames.Email, model.UserName),
                    new Claim(JwtRegisteredClaimNames.NameId, model.Id.ToString()),
                };
        var token = new JwtSecurityToken(_config["Jwt:Issuer"],
          _config["Jwt:Issuer"],
          claims,
          expires: DateTime.Now.AddMinutes(30),
          signingCredentials: creds);

Puis extraire le contenu

 var handler = new JwtSecurityTokenHandler();
        string authHeader = Request.Headers["Authorization"];
        authHeader = authHeader.Replace("Bearer ", "");
        var jsonToken = handler.ReadToken(authHeader);
        var tokenS = handler.ReadToken(authHeader) as JwtSecurityToken;

        var id = tokenS.Claims.First(claim => claim.Type == "nameid").Value;
0
Jinesh