Mendekode dan memverifikasi token JWT menggunakan System.IdentityModel.Tokens.Jwt

102

Saya telah menggunakan perpustakaan JWT untuk mendekode Token Web Json, dan ingin beralih ke implementasi JWT resmi Microsoft, System.IdentityModel.Tokens.Jwt .

Dokumentasinya sangat jarang, jadi saya mengalami kesulitan mencari cara untuk mencapai apa yang telah saya lakukan dengan perpustakaan JWT. Dengan pustaka JWT, ada metode Dekode yang mengambil JWT yang dikodekan base64 dan mengubahnya menjadi JSON yang kemudian dapat dideserialisasi. Saya ingin melakukan sesuatu yang serupa menggunakan System.IdentityModel.Tokens.Jwt, tetapi setelah cukup banyak menggali, tidak dapat mengetahui caranya.

Untuk apa nilainya, saya membaca token JWT dari cookie, untuk digunakan dengan kerangka identitas Google.

Bantuan apa pun akan dihargai.

w. Brian
sumber
Berikut adalah jawaban langsung tentang cara mengambil sertifikat google dan memverifikasi token - stackoverflow.com/questions/29757140/…
rothschild86

Jawaban:

148

Di dalam paket ada kelas yang disebut JwtSecurityTokenHandlerberasal dari System.IdentityModel.Tokens.SecurityTokenHandler. Dalam WIF ini adalah kelas inti untuk deserialising dan serialing security token.

Kelas memiliki ReadToken(String)metode yang akan mengambil string JWT berenkode base64 Anda dan mengembalikan a SecurityTokenyang mewakili JWT.

The SecurityTokenHandlerjuga memiliki ValidateToken(SecurityToken)metode yang mengambil SecurityTokendan membuat file ReadOnlyCollection<ClaimsIdentity>. Biasanya untuk JWT, ini akan berisi satu ClaimsIdentityobjek yang memiliki sekumpulan klaim yang mewakili properti JWT asli.

JwtSecurityTokenHandlermendefinisikan beberapa kelebihan tambahan untuk ValidateToken, khususnya, ClaimsPrincipal ValidateToken(JwtSecurityToken, TokenValidationParameters)kelebihan beban. The TokenValidationParametersargumen memungkinkan Anda untuk menentukan sertifikat penandatanganan tanda (sebagai daftar X509SecurityTokens). Ini juga memiliki kelebihan beban yang menjadikan JWT sebagai stringalih - alih SecurityToken.

Kode untuk melakukan ini agak rumit, tetapi dapat ditemukan di kode ( TokenValidationHandlerkelas) Global.asax.cx dalam contoh pengembang yang disebut "ADAL - Layanan Native App to REST - Otentikasi dengan ACS melalui Dialog Browser", yang terletak di

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

Alternatifnya, JwtSecurityTokenkelas memiliki metode tambahan yang tidak berada pada SecurityTokenkelas dasar , seperti Claimsproperti yang mendapatkan klaim yang terkandung tanpa melalui ClaimsIdentitycollection. Ia juga memiliki Payloadproperti yang mengembalikan JwtPayloadobjek yang memungkinkan Anda mendapatkan JSON mentah dari token. Itu tergantung pada skenario Anda, pendekatan mana yang paling tepat.

Dokumentasi umum (yaitu khusus non JWT) untuk SecurityTokenHandlerkelas ada di

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

Bergantung pada aplikasi Anda, Anda dapat mengonfigurasi penangan JWT ke dalam pipeline WIF persis seperti penangan lainnya.

Ada 3 sampel yang digunakan dalam berbagai jenis aplikasi di

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% 20Pengembang% 20Pengalaman% 20Tim & f% 5B1% 5D. Teks = Azure% 20AD% 20Pengembang% 20Pengalaman% 20Tim

Mungkin, satu akan sesuai dengan kebutuhan Anda atau setidaknya dapat beradaptasi dengan mereka.

Mike Goodwin
sumber
3
Saya sangat menghargai jawaban Anda. Jadi, setelah saya memiliki ClaimsIdentity, bagaimana cara memverifikasinya dengan kunci publik? Secara khusus, saya mencoba memverifikasi JWT alat identitas google terhadap kunci publik mereka ( gstatic.com/authtoolkit/cert/gitkit_cert.pem )
w.brian
4
Memperbarui jawaban saya - Saya tidak dapat memasukkan sumber lengkap untuk ini, tetapi saya mengarahkan Anda ke arah sampel pengembang yang sesuai. Semoga membantu.
Mike Goodwin
4
@ w.brian - Saya mencoba melakukan hal yang sama. Saya memiliki token yang dapat saya decode, dan kunci publik yang ingin saya verifikasi, tetapi bahkan melihat sampel ini saya kesulitan untuk melihat bagaimana saya melakukan ini. Apakah Anda memiliki petunjuk tentang kode yang benar-benar membantu Anda? Terima kasih.
Barguast
27

Saya hanya ingin tahu mengapa menggunakan beberapa pustaka untuk decoding dan verifikasi token JWT.

Token JWT yang dikodekan dapat dibuat menggunakan kodesemu berikut

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

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

var encodedJWT = payload + "." + signature;

Ini sangat mudah dilakukan tanpa perpustakaan khusus. Menggunakan kode berikut:

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

Token decoding adalah versi kebalikan dari kode di atas. Untuk memverifikasi tanda tangan Anda perlu sama dan membandingkan bagian tanda tangan dengan tanda tangan terhitung.

UPDATE: Bagi mereka yang sedang berjuang bagaimana melakukan encoding / decoding urlsafe base64, silakan lihat pertanyaan SO lainnya , dan juga wiki dan RFC

Regfor
sumber
2
Jawaban bagus. Meskipun karena Anda menampilkan penandatanganan berbasis HMAC di sini, mungkin masuk akal untuk mengetahui beberapa kerentanan kritis di pustaka yang menerapkan verifikasi HMAC seperti yang dijelaskan di situs Auth0 di sini: auth0.com/blog/2015/03/31/…
Sudhanshu Mishra
2
Saya merasa ini adalah jawaban terbaik. OP meminta info tentang JWT secara khusus yang artikel ini membahas dengan contoh yang jelas ..
webworm
15
Jawaban ini menjelaskan dan menunjukkan bagaimana en kode JWT ketika pertanyaannya adalah cukup jelas tentang de coding. Ini mungkin jawaban yang bagus tetapi ini adalah jawaban untuk pertanyaan yang sama sekali berbeda .
Deltics
2
@Deltics Saya pikir bahkan gelar ilmu komputer tidak diperlukan untuk menulis ulang algoritma pengkodean untuk memecahkan kode token. Jika Anda memahami cara menyandikan - Anda memahami cara mendekode
Regfor
33
Ide dari sebuah "jawaban" adalah untuk menjawab pertanyaan, bukan mengajukan teka-teki dengan mengharapkan seseorang memecahkan semacam teka-teki niat terbalik. Bedsides, mengetahui bagaimana encode tidak tidak selalu berarti bahwa Anda juga kemudian tahu bagaimana decode karena ini juga dapat melibatkan berurusan dengan token pihak ke-3 dan mengambil kunci untuk memverifikasi tanda tangan mereka, sebagai lawan hanya menggunakan kunci untuk menandatangani Anda sendiri. Bagaimanapun, jawaban yang tidak benar - benar menjawab pertanyaan per definisi bukanlah jawaban yang " lebih baik " jika dibandingkan dengan yang bisa , yang merupakan pengamatan yang saya tanggapi.
Deltics