Wie dekodiere ich JWT Token?

101

Ich verstehe nicht, wie diese Bibliothek funktioniert. Kannst du mir bitte helfen ?

Hier ist mein einfacher Code:

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

        var jsonToken = handler.ReadToken(stream);
    }

Dies ist der Fehler:

Die Zeichenfolge muss im kompakten JSON-Format vorliegen: Base64UrlEncodedHeader.Base64UrlEndcodedPayload.OPTIONAL, Base64UrlEncodedSignature '.

Wenn Sie den Stream auf der Website jwt.io kopieren , funktioniert er einwandfrei :)

Cooxkie
quelle
1
Die Website jwt, io dekodiert es, aber es gibt keine Signatur, sodass es ungültig ist.
Crowcoder
1
@ MichaelFreidgeim Sie haben Recht, es ist doppelte Frage ... aber die Antworten sind aufgrund der von Ihnen verwendeten
Versionsbibliothek

Antworten:

174

Ich habe die Lösung gefunden, ich habe nur vergessen, das Ergebnis zu besetzen:

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

Ich kann Ansprüche erhalten mit:

var jti = tokenS.Claims.First(claim => claim.Type == "jti").Value;
Cooxkie
quelle
2
Ich musste zuerst tokenS.Claims als Liste der Ansprüche wirken. ((List<Claim>)tokenS.Claims).ForEach(a => Console.WriteLine(a.Type.ToString() + " " + a.Value));
Rinaldi Segecin
12
Sie können auch Folgendes tun: handler.ReadJwtToken (tokenJwtReponse.access_token);
Thabiso Mofokeng
13
Entschuldigung, wenn dies offensichtlich sein sollte, aber woher kommt tokenJwtReponse.access_tokenes?
Jeff Stapleton
3
Woher kommt tokenJwtReponse.access_token?
3.
4
Wie andere bereits gefragt haben: Woher kommt "tokenJwtReponse.access_token"? Die Antwort enthält keine Definition oder Erklärung dafür, was die Antwort für viele von uns nutzlos und bedeutungslos macht.
Zeek2
33

new JwtSecurityTokenHandler().ReadToken("") wird a zurückgeben SecurityToken

new JwtSecurityTokenHandler().ReadJwtToken("") wird a zurückgeben JwtSecurityToken

Wenn Sie nur die von Ihnen verwendete Methode ändern, können Sie die Besetzung in der obigen Antwort vermeiden

dpix
quelle
16

Sie benötigen die geheime Zeichenfolge, mit der das Verschlüsselungstoken generiert wurde. Dieser Code funktioniert für mich:

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;
    }
Pato Milán
quelle
Warum rufen Sie auf, handler.ReadToken(token) as SecurityTokenwenn Sie es später als outParameter neu zuweisen? Gibt es eine Möglichkeit, die ValidateTokenfehlschlägt und der ursprüngliche Wert bleibt?
Krillgar
Richtiger Krillgar ist nicht unbedingt die Besetzung von SecurityToken
Pato Milán
Überprüft ValidateToken den Ablauf? Oder muss ich das selbst validieren, nachdem es dekodiert wurde?
Computrius
9

Unter Verwendung von .net Core-JWT-Paketen sind die Ansprüche verfügbar:

[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;
    }
}
jenson-button-event
quelle
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);

Dann extrahieren Sie den Inhalt

 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;
Jinesh
quelle
3

Die Ausweitung auf cooxkie Antwort und DPix Antwort, wenn Sie lesen gerade ein jwt Token (wie ein access_token von AD FS empfangen wird ), können Sie die Ansprüche in der jwt Token verschmelzen mit den Ansprüchen von „context.AuthenticationTicket.Identity“ Das könnte nicht haben die gleichen Ansprüche wie das JWT-Token.

Zur Veranschaulichung: In einem Authentifizierungscode-Fluss mit OpenID Connect können Sie nach der Authentifizierung eines Benutzers das Ereignis SecurityTokenValidated behandeln , das Ihnen einen Authentifizierungskontext bereitstellt. Anschließend können Sie das access_token als JWT-Token lesen und dann " Zusammenführen von "Token, die sich im access_token befinden, mit der Standardliste der Ansprüche, die als Teil der Benutzeridentität empfangen wurden:

    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);
    }
TamerDev
quelle