Come decodificare il token JWT?


102

Non capisco come funziona questa libreria. Potresti aiutarmi per favore ?

Ecco il mio semplice codice:

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

        var jsonToken = handler.ReadToken(stream);
    }

Questo è l'errore:

La stringa deve essere in formato JSON compatto, che ha il formato: Base64UrlEncodedHeader.Base64UrlEndcodedPayload.OPTIONAL, Base64UrlEncodedSignature '.

Se copi lo stream nel sito jwt.io , funziona bene :)


1
il sito jwt, io lo decodifica, ma non c'è la firma quindi non è valido.
Crowcoder


1
@MichaelFreidgeim hai ragione, è una domanda duplicata ... ma le risposte sono diverse a causa della libreria di versioni che usi
Cooxkie

Risposte:


176

Ho trovato la soluzione, ho appena dimenticato di trasmettere il risultato:

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

Posso ottenere reclami utilizzando:

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

2
Ho dovuto prima lanciare tokenS.Claims come elenco di reclami. ((List<Claim>)tokenS.Claims).ForEach(a => Console.WriteLine(a.Type.ToString() + " " + a.Value));
Rinaldi Segecin

12
Puoi anche fare: handler.ReadJwtToken (tokenJwtReponse.access_token);
Thabiso Mofokeng

13
Scusa se questo dovrebbe essere ovvio ma da dove viene tokenJwtReponse.access_token?
Jeff Stapleton

3
Da dove proviene tokenJwtReponse.access_token?
3iL

4
Come altri hanno già messo in dubbio: da dove viene "tokenJwtReponse.access_token"? Non c'è una definizione o una dichiarazione per questo nella risposta, rendendo la risposta inutile e priva di significato per molti di noi.
Zeek2

33

new JwtSecurityTokenHandler().ReadToken("") restituirà un file SecurityToken

new JwtSecurityTokenHandler().ReadJwtToken("") restituirà un file JwtSecurityToken

Se cambi solo il metodo che stai usando, puoi evitare il cast nella risposta sopra


16

È necessaria la stringa segreta utilizzata per generare il token di crittografia. Questo codice funziona per 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;
    }

Perché chiami handler.ReadToken(token) as SecurityTokenquando lo riassegni come outparametro in seguito? C'è una possibilità che ValidateTokenfallisce e il valore originale viene mantenuto?
krillgar

A destra Krillgar non è necessario il cast di SecurityToken
Pato Milán

ValidateToken controlla la scadenza? O devo convalidarlo io stesso dopo che è stato decodificato?
computrius

9

Utilizzando i pacchetti jwt .net core, le attestazioni sono disponibili:

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

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

Quindi estrai il contenuto

 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;

3

Estendendo su cooxkie answer e dpix answer, quando stai leggendo un token jwt (come un access_token ricevuto da AD FS), puoi unire le attestazioni nel token jwt con le attestazioni da "context.AuthenticationTicket.Identity" che potrebbero non hanno lo stesso insieme di attestazioni del token jwt.

Per illustrare, in un flusso di codice di autenticazione che utilizza OpenID Connect, dopo che un utente è stato autenticato, puoi gestire l'evento SecurityTokenValidated che ti fornisce un contesto di autenticazione, quindi puoi usarlo per leggere il token di accesso come token jwt, quindi puoi " unisci "token che si trovano in access_token con l'elenco standard di attestazioni ricevute come parte dell'identità dell'utente:

    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);
    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.