Bagaimana cara memecahkan kode JWT Token?

103

Saya tidak mengerti cara kerja perpustakaan ini. Bisakah kamu membantuku ?

Ini kode sederhana saya:

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

        var jsonToken = handler.ReadToken(stream);
    }

Ini adalah kesalahannya:

String harus dalam format JSON yang ringkas, dalam bentuk: Base64UrlEncodedHeader.Base64UrlEndcodedPayload.OPTIONAL, Base64UrlEncodedSignature '.

Jika Anda menyalin aliran di situs web jwt.io , itu berfungsi dengan baik :)

Cooxkie
sumber
1
situs jwt, io menerjemahkannya, tetapi tidak ada tanda tangan sehingga tidak valid.
Crowcoder
1
@MichaelFreidgeim Anda benar itu pertanyaan duplikat ... tetapi jawabannya berbeda karena pustaka versi yang Anda gunakan
Cooxkie

Jawaban:

180

Saya menemukan solusinya, saya hanya lupa untuk Cast hasilnya:

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

Saya bisa mendapatkan Klaim menggunakan:

var jti = tokenS.Claims.First(claim => claim.Type == "jti").Value;
Cooxkie
sumber
2
Saya harus melemparkan tokenS. Klaim sebagai Daftar Klaim terlebih dahulu. ((List<Claim>)tokenS.Claims).ForEach(a => Console.WriteLine(a.Type.ToString() + " " + a.Value));
Rinaldi Segecin
12
Anda juga dapat melakukan: handler.ReadJwtToken (tokenJwtReponse.access_token);
Thabiso Mofokeng
14
Maaf jika ini harus jelas tetapi dari mana tokenJwtReponse.access_tokenasalnya?
Jeff Stapleton
4
Dari manakah tokenJwtReponse.access_token berasal?
3iL
4
Seperti yang telah dipertanyakan orang lain: dari mana "tokenJwtReponse.access_token" berasal? Tidak ada definisi atau pernyataan untuk itu dalam jawaban, membuat jawaban tidak berguna dan tidak berarti bagi banyak dari kita.
Zeek2
35

new JwtSecurityTokenHandler().ReadToken("") akan mengembalikan SecurityToken

new JwtSecurityTokenHandler().ReadJwtToken("") akan mengembalikan JwtSecurityToken

Jika Anda hanya mengubah metode yang Anda gunakan, Anda dapat menghindari cast dalam jawaban di atas

dpix
sumber
16

Anda memerlukan string rahasia yang digunakan untuk menghasilkan token enkripsi. Kode ini berfungsi untuk saya:

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
sumber
Mengapa Anda menelepon handler.ReadToken(token) as SecurityTokensaat Anda menetapkannya kembali sebagai outparameter Anda nanti? Apakah ada kemungkinan yang ValidateTokengagal dan nilai aslinya disimpan?
krillgar
Krillgar kanan tidak perlu masuk ke SecurityToken
Pato Milán
Apakah ValidateToken memeriksa kedaluwarsa? Atau apakah saya perlu memvalidasinya sendiri setelah didekodekan?
computrius
9

Menggunakan paket .net core jwt, Klaim tersedia:

[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
sumber
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);

Kemudian ekstrak konten

 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
sumber
3

Memperluas jawaban cooxkie , dan dpix jawaban , saat Anda membaca token jwt (seperti access_token yang diterima dari AD FS), Anda dapat menggabungkan klaim dalam token jwt dengan klaim dari "context.AuthenticationTicket.Identity" yang mungkin tidak memiliki kumpulan klaim yang sama dengan token jwt.

Sebagai ilustrasi, dalam alur Kode Otentikasi menggunakan OpenID Connect, setelah pengguna diautentikasi, Anda dapat menangani peristiwa SecurityTokenValidated yang memberi Anda konteks otentikasi, lalu Anda dapat menggunakannya untuk membaca access_token sebagai token jwt, lalu Anda dapat " gabungkan "token yang ada di access_token dengan daftar standar klaim yang diterima sebagai bagian dari identitas pengguna:

    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
sumber