System.IdentityModel.Tokens.Jwt kullanarak JWT belirtecinin kodunu çözme ve doğrulama


103

Bir Json Web Token kodunu çözmek için JWT kitaplığını kullanıyorum ve Microsoft'un resmi JWT uygulaması olan System.IdentityModel.Tokens.Jwt'ye geçmek istiyorum .

Dokümantasyon çok seyrek, bu yüzden JWT kütüphanesiyle yaptıklarımı nasıl başaracağımı bulmakta zorlanıyorum. JWT kütüphanesi ile, base64 kodlu JWT'yi alıp JSON'a dönüştüren ve ardından serileştirilmemiş hale getirilebilen bir Decode yöntemi vardır. System.IdentityModel.Tokens.Jwt kullanarak benzer bir şey yapmak isterdim, ancak makul miktarda kazı yaptıktan sonra nasıl olduğunu anlayamıyorum.

Değeri ne olursa olsun, Google'ın kimlik çerçevesiyle kullanmak için bir çerezden JWT belirtecini okuyorum.

Herhangi bir yardım memnuniyetle karşılanacaktır.



İşte Google sertifikalarının nasıl alınacağına ve jetonun nasıl doğrulanacağına dair uygulamalı bir cevap - stackoverflow.com/questions/29757140/…
rothschild86

Yanıtlar:


153

Paketin içinde JwtSecurityTokenHandlertüretilen bir sınıf var System.IdentityModel.Tokens.SecurityTokenHandler. WIF'de bu, güvenlik belirteçlerini serileştirme ve serileştirme için temel sınıftır.

Sınıf, ReadToken(String)base64 kodlu JWT dizenizi alacak ve JWT'yi SecurityTokentemsil eden bir döndüren bir yönteme sahiptir .

SecurityTokenHandlerAyrıca sahiptir ValidateToken(SecurityToken)Şu Verilerinizi alır yöntemi SecurityTokenve bir oluşturur ReadOnlyCollection<ClaimsIdentity>. Genellikle JWT için bu ClaimsIdentity, orijinal JWT'nin özelliklerini temsil eden bir dizi iddiaya sahip tek bir nesne içerir .

JwtSecurityTokenHandlerValidateTokenözellikle aşırı yüke sahip olduğu için bazı ek aşırı yükleri tanımlar ClaimsPrincipal ValidateToken(JwtSecurityToken, TokenValidationParameters). Bağımsız TokenValidationParametersdeğişken, belirteç imzalama sertifikasını (listesi olarak X509SecurityTokens) belirtmenize izin verir . Ayrıca, JWT'yi a stringyerine bir SecurityToken.

Bunu yapacak kod oldukça karmaşıktır, ancak Global.asax.cx kodunda ( TokenValidationHandlersınıf), "ADAL - Yerel Uygulamadan REST hizmetine - ACS ile Tarayıcı İletişim Kutusu aracılığıyla Kimlik Doğrulama" adlı geliştirici örneğinde bulunabilir.

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

Alternatif olarak, sınıfın, koleksiyona gitmeden içerilen talepleri alan bir özellik gibi JwtSecurityTokentemel SecurityTokensınıfta olmayan ek yöntemleri vardır . Ayrıca , belirtecin ham JSON'una ulaşmanıza izin veren bir nesne döndüren bir özelliğe de sahiptir . Senaryonuza en uygun yaklaşıma bağlıdır.ClaimsClaimsIdentityPayloadJwtPayload

SecurityTokenHandlerSınıf için genel (yani JWT'ye özgü olmayan) dokümantasyon şu adrestedir :

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

Uygulamanıza bağlı olarak, JWT işleyicisini diğer herhangi bir işleyici gibi WIF ardışık düzenine yapılandırabilirsiniz.

Farklı uygulama türlerinde kullanımda olan 3 örneği vardır.

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

Muhtemelen, biri ihtiyaçlarınızı karşılayacak veya en azından bunlara uyarlanabilir.


3
Cevabınızı gerçekten takdir ediyorum. Öyleyse, ClaimsIdentity'ye sahip olduğumda, bunu bir genel anahtara göre nasıl doğrulayabilirim? Özellikle, bir google kimlik araç seti JWT'yi genel anahtarlarına göre doğrulamaya çalışıyorum ( gstatic.com/authtoolkit/cert/gitkit_cert.pem )
w.brian,

4
Cevabımı güncelledim - Bunun için tam kaynağı sığdıramadım, ancak sizi uygun geliştirici örneğine yönlendirdim. Umarım yardımcı olur.
Mike Goodwin

4
@ w.brian - Ben de aynısını yapmaya çalışıyorum. Çözebileceğim bir jetonum ve doğrulamak istediğim bir genel anahtarım var, ancak bu örneklere baktığımda bile bunu nasıl yaptığımı görmekte zorlanıyorum. Hangi kodun size gerçekten yardımcı olduğuna dair herhangi bir işaretiniz var mı? Teşekkürler.
Barguast

28

JWT token kod çözme ve doğrulama için neden bazı kitaplıkları kullanmam gerektiğini merak ediyorum.

Kodlanmış JWT jetonu, aşağıdaki sözde kod kullanılarak oluşturulabilir

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

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

var encodedJWT = payload + "." + signature;

Herhangi bir özel kütüphane olmadan yapmak çok kolaydır. Aşağıdaki kodu kullanarak:

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

Belirteç çözme işlemi, yukarıdaki kodun tersine çevrilmiş halidir. İmzayı doğrulamak için, imza bölümünü hesaplanmış imza ile karşılaştırmanız gerekir.

GÜNCELLEME: Base64 urlsafe kodlama / kod çözme konusunda nasıl zorluk çekenler için lütfen başka bir SO sorusuna ve ayrıca wiki ve RFC'lere bakın.


2
Güzel cevap. Burada HMAC tabanlı imzalama gösterdiğiniz için, aşağıdaki Auth0 sitesinde ayrıntılı olarak açıklandığı gibi HMAC doğrulamasını uygulayan kütüphanelerdeki bazı kritik güvenlik açıklarının farkında olmak mantıklı olabilir: auth0.com/blog/2015/03/31/…
Mishra

2
Bunun en iyi cevap olduğunu hissediyorum. OP, JWT hakkında özellikle bu makalenin net bir örnekle ele aldığı bilgi istedi.
webworm

15
Bu cevap açıklar ve nasıl yapılacağını gösterir tr kodu bir JWT'de soru hakkında oldukça net olduğunda de kodlama. Bu güzel bir cevap olabilir ama tamamen farklı bir sorunun cevabıdır .
Deltics

34
Bir "cevap" fikri, bir soruyu ele almaktır, birisinin bir tür ters-niyet bulmacasını çözmesini bekleyerek bir bulmaca oluşturmak değil. Nasıl encode bilerek bedsides, yok değil mutlaka nasıl kod çözme için bu da 3. parti simgeleri ile uğraşan ve onların imzalarını doğrulamak için tuşları alınırken içerebilir olduğundan, sadece kendi imzalamak için bir anahtar kullanarak karşıt olarak ayrıca sonra, biliyorum anlamına gelir. Her durumda, yok bir cevap değil aslında tanım olarak soruya cevap olduğunu değil " daha iyi bir oranla" cevabı yok ben yanıt olarak geldi hangi gözlem olan.
Deltics

3
Ne yaptığınızı gerçekten bilmiyorsanız, güvenlikle ilgili parçaları kendiniz kodlamayın. Her zaman kolaylıkla yanlış yapabileceğiniz bir şeyler vardır. Savunmasız jwt kitaplıklarının var olduğu gerçeği, JWT'yi bu kitaplıkların yazarlarından daha iyi bildiğinizi gerçekten düşünmüyorsanız, bunu kendiniz kodlamanın kötü bir fikir olduğunun kanıtıdır. Bununla birlikte, bu cevap JWT'yi anlamak için hala yararlıdır.
Christopher K.,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.