JWTトークンをデコードする方法は?


101

このライブラリの仕組みがわかりません。私を手伝ってくれますか ?

これが私の簡単なコードです:

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

        var jsonToken = handler.ReadToken(stream);
    }

これはエラーです:

文字列は、Base64UrlEncodedHeader.Base64UrlEndcodedPayload.OPTIONAL、Base64UrlEncodedSignature 'という形式のコンパクトなJSON形式である必要があります。

jwt.io Webサイトでストリームをコピーすると、正常に動作します:)


1
jwt、ioサイトはそれをデコードしますが、署名がないため無効です。
クロウコーダー2016


1
@MichaelFreidgeim正解です質問が重複しています...しかし、使用するバージョンライブラリが原因で回答が異なります
Cooxkie

回答:


175

私は解決策を見つけました、結果をキャストするのを忘れました:

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

私は請求を得ることができます:

var jti = tokenS.Claims.First(claim => claim.Type == "jti").Value;

2
最初に、クレームのリストとしてtokenS.Claimsをキャストする必要がありました。((List<Claim>)tokenS.Claims).ForEach(a => Console.WriteLine(a.Type.ToString() + " " + a.Value));
リナルディセゲシン2017

12
次のこともできます:handler.ReadJwtToken(tokenJwtReponse.access_token);
タビソモフォケン18

13
これは明らかなはずですが、どこtokenJwtReponse.access_tokenから来たのですか?
ジェフステープルトン

3
tokenJwtReponse.access_tokenはどこから来るのですか?
3iL、

4
他の人がすでに質問したように: "tokenJwtReponse.access_token"はどこから来たのですか?答えにはそれの定義も宣言もないため、多くの人にとって答えは役に立たず、意味がありません。
Zeek2

33

new JwtSecurityTokenHandler().ReadToken("") を返します SecurityToken

new JwtSecurityTokenHandler().ReadJwtToken("") を返します JwtSecurityToken

使用しているメソッドを変更するだけで、上記の回答のキャストを回避できます


16

暗号化トークンの生成に使用された秘密の文字列が必要です。このコードは私にとってはうまくいきます:

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

後でパラメーターhandler.ReadToken(token) as SecurityTokenとして再割り当てするときに呼び出すのはなぜoutですか?ValidateToken失敗して元の値が保持される可能性はありますか?
オキアミ

右krillgarはセキュリティトークンにnesessaryキャストではありません
パトミラン

ValidateTokenは有効期限をチェックしますか?それとも、デコードされた後に自分自身を検証する必要がありますか?
computrius

9

.netコアjwtパッケージを使用すると、クレームを利用できます。

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

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

次にコンテンツを抽出します

 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;

3

cowtkieの回答とdpixの回答を拡張して、jwtトークン(AD FSから受け取ったaccess_tokenなど)を読み取っているときに、jwtトークン内のクレームを「context.AuthenticationTicket.Identity」からのクレームとマージできます。 jwtトークンと同じクレームのセットを持っています。

たとえば、OpenID Connectを使用した認証コードフローでは、ユーザーが認証された後、認証トークンを提供するSecurityTokenValidatedイベントを処理し、それを使用してaccess_tokenをjwtトークンとして読み取ることができます。 access_tokenにあるトークンを、ユーザーIDの一部として受け取ったクレームの標準リストとマージします。

    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);
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.