How to decode JWT Token?

I don't understand how this library works. Could you help me please ?

Here is my simple code :

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

        var jsonToken = handler.ReadToken(stream);
    }

This is the error :

The string needs to be in compact JSON format, which is of the form: Base64UrlEncodedHeader.Base64UrlEndcodedPayload.OPTIONAL,Base64UrlEncodedSignature'.

If you copy the stream in jwt.io website, it works fine :)


Solution 1:

I found the solution, I just forgot to Cast the result:

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

Or, without the cast:

var token = "[encoded jwt]";  
var handler = new JwtSecurityTokenHandler();
var jwtSecurityToken = handler.ReadJwtToken(token);

I can get Claims using:

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

Solution 2:

new JwtSecurityTokenHandler().ReadToken("") will return a SecurityToken

new JwtSecurityTokenHandler().ReadJwtToken("") will return a JwtSecurityToken

If you just change the method you are using you can avoid the cast in the above answer

Solution 3:

You need the secret string which was used to generate encrypt token. This code works for me:

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;
    }

Solution 4:

Using .net core jwt packages, the Claims are available:

[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;
    }
}

Solution 5:

  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);

Then extract content

 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;