Dekodieren und Überprüfen des JWT-Tokens mit System.IdentityModel.Tokens.Jwt

98

Ich habe die JWT- Bibliothek zum Dekodieren eines Json-Web-Tokens verwendet und möchte zur offiziellen JWT-Implementierung von Microsoft, System.IdentityModel.Tokens.Jwt , wechseln .

Die Dokumentation ist sehr spärlich, daher fällt es mir schwer, herauszufinden, wie ich das erreichen kann, was ich mit der JWT-Bibliothek gemacht habe. Mit der JWT-Bibliothek gibt es eine Decode-Methode, die das base64-codierte JWT in JSON umwandelt, das dann deserialisiert werden kann. Ich würde gerne etwas Ähnliches mit System.IdentityModel.Tokens.Jwt machen, kann aber nach einigem Graben nicht herausfinden, wie.

Für das, was es wert ist, lese ich das JWT-Token aus einem Cookie zur Verwendung mit dem Identitätsframework von Google.

Jede Hilfe wäre dankbar.

w.brian
quelle
Hier finden Sie eine praktische Antwort zum Abrufen von Google-Zertifikaten und zum Überprüfen des Tokens - stackoverflow.com/questions/29757140/…
rothschild86

Antworten:

146

Innerhalb des Pakets gibt es eine Klasse namens, JwtSecurityTokenHandlerdie von abgeleitet ist System.IdentityModel.Tokens.SecurityTokenHandler. In WIF ist dies die Kernklasse für das Deserialisieren und Serialisieren von Sicherheitstoken.

Die Klasse verfügt über eine ReadToken(String)Methode, die Ihre Base64-codierte JWT-Zeichenfolge verwendet und eine zurückgibt, SecurityTokendie die JWT darstellt.

Das SecurityTokenHandlerhat auch eine ValidateToken(SecurityToken)Methode, die Ihre nimmt SecurityTokenund eine erstellt ReadOnlyCollection<ClaimsIdentity>. Normalerweise enthält dies für JWT ein einzelnes ClaimsIdentityObjekt mit einer Reihe von Ansprüchen, die die Eigenschaften des ursprünglichen JWT darstellen.

JwtSecurityTokenHandlerdefiniert einige zusätzliche Überlastungen ValidateToken, insbesondere für eine ClaimsPrincipal ValidateToken(JwtSecurityToken, TokenValidationParameters)Überlastung. Mit diesem TokenValidationParametersArgument können Sie das Token-Signatur-Zertifikat (als Liste von X509SecurityTokens) angeben . Es hat auch eine Überlastung, die die JWT stringeher als eine als eine nimmt SecurityToken.

Der Code dafür ist ziemlich kompliziert, befindet sich jedoch im Global.asax.cx-Code ( TokenValidationHandlerKlasse) im Entwicklerbeispiel "ADAL - Native App für REST-Dienst - Authentifizierung mit ACS über den Browser-Dialog" unter

http://code.msdn.microsoft.com/AAL-Native-App-to-REST-de57f2cc

Alternativ verfügt die JwtSecurityTokenKlasse über zusätzliche Methoden, die sich nicht in der Basisklasse befinden SecurityToken, z. B. eine ClaimsEigenschaft, die die enthaltenen Ansprüche abruft, ohne die ClaimsIdentityAuflistung zu durchlaufen. Es hat auch eine PayloadEigenschaft, die ein JwtPayloadObjekt zurückgibt , mit dem Sie den unformatierten JSON des Tokens abrufen können. Es hängt von Ihrem Szenario ab, welcher Ansatz am besten geeignet ist.

Die allgemeine (dh nicht JWT-spezifische) Dokumentation für die SecurityTokenHandlerKlasse finden Sie unter

http://msdn.microsoft.com/en-us/library/system.identitymodel.tokens.securitytokenhandler.aspx

Abhängig von Ihrer Anwendung können Sie den JWT-Handler genau wie jeden anderen Handler in der WIF-Pipeline konfigurieren.

Es gibt 3 Beispiele davon, die in verschiedenen Anwendungsarten bei verwendet werden

http://code.msdn.microsoft.com/site/search?f%5B0%5D.Type=SearchText&f%5B0%5D.Value=aal&f%5B1%5D.Type=User&f%5B1%5D.Value=Azure%% 20AD% 20Developer% 20Experience% 20Team & f% 5B1% 5D.Text = Azure% 20AD% 20Developer% 20Experience% 20Team

Wahrscheinlich wird einer Ihren Bedürfnissen entsprechen oder zumindest an diese angepasst werden können.

Mike Goodwin
quelle
3
Ich schätze Ihre Antwort sehr. Wie überprüfe ich die ClaimsIdentity anhand eines öffentlichen Schlüssels? Insbesondere versuche ich, ein Google Identity Toolkit JWT anhand seines öffentlichen Schlüssels ( gstatic.com/authtoolkit/cert/gitkit_cert.pem ) zu überprüfen
w.brian
4
Meine Antwort wurde aktualisiert. Ich konnte nicht die vollständige Quelle dafür einfügen, habe Sie jedoch auf das entsprechende Entwicklerbeispiel hingewiesen. Ich hoffe es hilft.
Mike Goodwin
4
@ w.brian - Ich versuche das gleiche zu tun. Ich habe ein Token, das ich dekodieren kann, und einen öffentlichen Schlüssel, den ich überprüfen möchte, aber selbst wenn ich mir diese Beispiele ansehe, habe ich Schwierigkeiten zu sehen, wie ich das mache. Haben Sie Hinweise darauf, welcher Code Ihnen tatsächlich geholfen hat? Vielen Dank.
Barguast
24

Ich frage mich nur, warum ich überhaupt einige Bibliotheken für die Dekodierung und Verifizierung von JWT-Token verwenden soll.

Das codierte JWT-Token kann mit dem folgenden Pseudocode erstellt werden

var headers = base64URLencode(myHeaders);
var claims = base64URLencode(myClaims);
var payload = header + "." + claims;

var signature = base64URLencode(HMACSHA256(payload, secret));

var encodedJWT = payload + "." + signature;

Es ist sehr einfach, auf eine bestimmte Bibliothek zu verzichten. Verwenden Sie folgenden Code:

using System;
using System.Text;
using System.Security.Cryptography;

public class Program
{   
    // More info: https://stormpath.com/blog/jwt-the-right-way/
    public static void Main()
    {           
        var header = "{\"typ\":\"JWT\",\"alg\":\"HS256\"}";
        var claims = "{\"sub\":\"1047986\",\"email\":\"[email protected]\",\"given_name\":\"John\",\"family_name\":\"Doe\",\"primarysid\":\"b521a2af99bfdc65e04010ac1d046ff5\",\"iss\":\"http://example.com\",\"aud\":\"myapp\",\"exp\":1460555281,\"nbf\":1457963281}";

        var b64header = Convert.ToBase64String(Encoding.UTF8.GetBytes(header))
            .Replace('+', '-')
            .Replace('/', '_')
            .Replace("=", "");
        var b64claims = Convert.ToBase64String(Encoding.UTF8.GetBytes(claims))
            .Replace('+', '-')
            .Replace('/', '_')
            .Replace("=", "");

        var payload = b64header + "." + b64claims;
        Console.WriteLine("JWT without sig:    " + payload);

        byte[] key = Convert.FromBase64String("mPorwQB8kMDNQeeYO35KOrMMFn6rFVmbIohBphJPnp4=");
        byte[] message = Encoding.UTF8.GetBytes(payload);

        string sig = Convert.ToBase64String(HashHMAC(key, message))
            .Replace('+', '-')
            .Replace('/', '_')
            .Replace("=", "");

        Console.WriteLine("JWT with signature: " + payload + "." + sig);        
    }

    private static byte[] HashHMAC(byte[] key, byte[] message)
    {
        var hash = new HMACSHA256(key);
        return hash.ComputeHash(message);
    }
}

Die Token-Dekodierung ist eine umgekehrte Version des obigen Codes. Um die Signatur zu überprüfen, benötigen Sie dieselbe und vergleichen den Signaturteil mit der berechneten Signatur.

UPDATE: Für diejenigen, die Schwierigkeiten haben, Base64-URL-sichere Codierung / Decodierung durchzuführen, lesen Sie bitte eine andere SO-Frage sowie Wiki und RFCs

Regfor
quelle
2
Gute Antwort. Da Sie hier eine HMAC-basierte Signatur anzeigen, kann es sinnvoll sein, einige kritische Schwachstellen in Bibliotheken zu kennen, die die HMAC-Überprüfung implementieren, wie auf der Auth0-Website hier beschrieben: auth0.com/blog/2015/03/31/…
Sudhanshu Mishra
2
Ich denke, das ist die beste Antwort. Das OP forderte Informationen zu JWT an, die in diesem Artikel mit einem klaren Beispiel behandelt werden.
Webworm
13
Diese Antwort erklärt und demonstriert , wie man en Code ein JWT , wenn die Frage ganz eindeutig über de Codierung. Dies mag eine nette Antwort sein, aber es ist eine Antwort auf eine ganz andere Frage .
Deltics
2
@Deltics Ich denke, dass nicht einmal ein Abschluss in Informatik erforderlich ist, um den Codierungsalgorithmus neu zu schreiben, um das Token zu decodieren. Wenn Sie verstehen, wie man codiert - Sie verstehen, wie man decodiert
Regfor
30
Die Idee einer "Antwort" besteht darin, eine Frage zu beantworten und kein Rätsel zu stellen, indem erwartet wird, dass jemand eine Art Rätsel mit umgekehrter Absicht löst. Bedsides, das Wissen, wie man codiert, bedeutet nicht unbedingt, dass Sie dann auch wissen, wie man decodiert, da dies auch den Umgang mit Token von Drittanbietern und das Abrufen von Schlüsseln zur Überprüfung ihrer Signaturen beinhalten kann, anstatt einfach einen Schlüssel zum Signieren Ihrer eigenen zu verwenden. Auf jedem Fall eine Antwort , die nicht nicht wirklich die Frage nach Definition beantworten ist nicht die „ besser “ als Antwort , wenn auf einen Vergleich, der tut , was die Beobachtung ist , auf die ich reagiere.
Deltics