Decodifica e verifica del token JWT utilizzando System.IdentityModel.Tokens.Jwt


102

Ho utilizzato la libreria JWT per decodificare un token Web Json e vorrei passare all'implementazione JWT ufficiale di Microsoft, System.IdentityModel.Tokens.Jwt .

La documentazione è molto scarsa, quindi ho difficoltà a capire come realizzare ciò che ho fatto con la libreria JWT. Con la libreria JWT, esiste un metodo Decode che prende il JWT con codifica base64 e lo trasforma in JSON che può quindi essere deserializzato. Mi piacerebbe fare qualcosa di simile usando System.IdentityModel.Tokens.Jwt, ma dopo un bel po 'di ricerche, non riesco a capire come.

Per quello che vale, sto leggendo il token JWT da un cookie, da utilizzare con il framework di identità di Google.

Qualsiasi aiuto sarebbe apprezzato.



Ecco una risposta pratica su come recuperare i certificati Google e verificare il token: stackoverflow.com/questions/29757140/…
rothschild86

Risposte:


148

All'interno del pacchetto c'è una classe chiamata JwtSecurityTokenHandlerche deriva da System.IdentityModel.Tokens.SecurityTokenHandler. In WIF questa è la classe principale per deserializzare e serializzare i token di sicurezza.

La classe ha un ReadToken(String)metodo che prenderà la stringa JWT codificata in base64 e restituirà un SecurityTokenche rappresenta il JWT.

L' SecurityTokenHandlerha anche un ValidateToken(SecurityToken)metodo che prende la vostra SecurityTokene crea un ReadOnlyCollection<ClaimsIdentity>. Di solito per JWT, questo conterrà un singolo ClaimsIdentityoggetto che ha una serie di attestazioni che rappresentano le proprietà del JWT originale.

JwtSecurityTokenHandlerdefinisce alcuni sovraccarichi aggiuntivi per ValidateToken, in particolare, ha un ClaimsPrincipal ValidateToken(JwtSecurityToken, TokenValidationParameters)sovraccarico. L' TokenValidationParametersargomento consente di specificare il certificato di firma del token (come un elenco di X509SecurityTokens). Ha anche un sovraccarico che prende il JWT come stringun file SecurityToken.

Il codice per farlo è piuttosto complicato, ma può essere trovato nel codice ( TokenValidationHandlerclasse) Global.asax.cx nell'esempio dello sviluppatore chiamato "ADAL - Native App to REST service - Authentication with ACS via Browser Dialog", situato in

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

In alternativa, la JwtSecurityTokenclasse dispone di metodi aggiuntivi che non si trovano nella SecurityTokenclasse di base , ad esempio una Claimsproprietà che ottiene le attestazioni contenute senza passare attraverso la ClaimsIdentityraccolta. Ha anche una Payloadproprietà che restituisce un JwtPayloadoggetto che ti consente di ottenere il JSON grezzo del token. Dipende dal tuo scenario quale approccio è più appropriato.

La documentazione generale (cioè non specifica di JWT) per la SecurityTokenHandlerclasse si trova in

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

A seconda della tua applicazione, puoi configurare il gestore JWT nella pipeline WIF esattamente come qualsiasi altro gestore.

Ce ne sono 3 esempi in uso in diversi tipi di applicazione su

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% 20Esperienza% 20Team & f% 5B1% 5D.Text = Azure% 20AD% 20Developer% 20Experience% 20Team

Probabilmente, uno soddisferà le tue esigenze o almeno sarà adattabile a loro.


3
Apprezzo molto la tua risposta. Quindi, una volta che ho ClaimsIdentity, come posso verificarlo con una chiave pubblica? In particolare, sto cercando di verificare un JWT del toolkit di identità di Google rispetto alla loro chiave pubblica ( gstatic.com/authtoolkit/cert/gitkit_cert.pem )
w.brian

4
Ho aggiornato la mia risposta: non sono riuscito a inserire la fonte completa per questo, ma ti ho indirizzato nella direzione dell'esempio di sviluppatore appropriato. Spero che sia d'aiuto.
Mike Goodwin

4
@ w.brian - Sto cercando di fare lo stesso. Ho un token che posso decodificare e una chiave pubblica che voglio verificare, ma anche guardando questi campioni faccio fatica a vedere come lo faccio. Hai qualche indicazione su quale codice ti ha effettivamente aiutato? Grazie.
Barguast

27

Mi chiedo solo perché utilizzare alcune librerie per la decodifica e la verifica dei token JWT.

Il token JWT codificato può essere creato utilizzando il seguente pseudocodice

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

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

var encodedJWT = payload + "." + signature;

È molto facile fare a meno di una libreria specifica. Utilizzando il seguente codice:

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\":\"jon.doe@eexample.com\",\"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);
    }
}

La decodifica del token è la versione invertita del codice sopra. Per verificare la firma, sarà necessario lo stesso e confrontare la parte della firma con la firma calcolata.

AGGIORNAMENTO: Per coloro che stanno lottando su come eseguire la codifica / decodifica urlsafe base64, vedere un'altra domanda SO , e anche wiki e RFC


2
Bella risposta. Sebbene qui mostri la firma basata su HMAC, può avere senso essere a conoscenza di alcune vulnerabilità critiche nelle librerie che implementano la verifica HMAC come descritto in dettaglio sul sito Auth0 qui: auth0.com/blog/2015/03/31/…
Sudhanshu Mishra

2
Penso che questa sia la risposta migliore. L'OP ha richiesto informazioni su JWT specificamente che questo articolo affronta con un chiaro esempio ..
webworm

15
Questa risposta spiega e dimostra come it codice di JWT, quando la questione è abbastanza chiaramente di de codifica. Questa può essere una bella risposta, ma è una risposta a una domanda completamente diversa .
Deltics

2
@Deltics Penso che anche la laurea in informatica non sia necessaria per riscrivere l'algoritmo di codifica per decodificare il token. Se capisci come codificare - capisci come decodificare
Regfor

33
L'idea di una "risposta" è affrontare una domanda, non porre un enigma aspettandosi che qualcuno risolva una sorta di rompicapo con intenzione inversa. Comodini, saper codificare fa non significa necessariamente che anche voi allora sapete come decodificare poiché questo può anche comportare che fare con 3rd gettoni di partito e il recupero delle chiavi di verificare le loro firme, invece di semplicemente utilizzando una chiave per firmare il proprio. In ogni caso, una risposta che non non realmente rispondere alla domanda, per definizione, è non è il " migliore " risposta quando paragonato a uno che fa , che è l'osservazione a cui stavo rispondendo.
Deltics
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.