簡體   English   中英

JSON Web Tokens Not Decodable on jwt.io: “JWT payload is not a valid JSON object”

[英]JSON Web Tokens Not Decodable on jwt.io: “JWT payload is not a valid JSON object”

使用下面的代碼,我可以構建一個解碼的 JSON Web 令牌( decodedToken )。 當我將其粘貼到https://jwt.io上的調試器中時,header 和有效負載正確顯示在右側。 但是,當我將編碼的令牌 ( encodedToken ) 粘貼到調試器中時,我會收到以下消息:

看起來您的 JWT 有效負載不是有效的 JSON object。 根據https://tools.ietf.org/html/rfc7519#section-7,JWT有效負載必須是頂級 JSON 對象。

它還在底部用大紅色字母表示“無效簽名”。

此外,使用編碼令牌時,header 區域顯示我解碼的 header,有效負載區域顯示我的整個解碼令牌 所以 jwt.io 以某種方式成功解碼了 JWT。 但它不應該嘗試將整個解碼令牌的 JSON 解析為一個單元。 它應該嘗試分別解析 header 的 JSON 和有效負載部分。

我想知道為什么 jwt.io 不能完全了解我的編碼令牌的有效負載。 decodedTokenencodedToken的值在下面的源代碼中顯示為注釋。 謝謝你。

private static string GetEncodedToken(string privateKey)
{
    JObject header = JObject.FromObject(new { alg = "ES384", typ = "JWT" });
    JObject payload = JObject.FromObject(new { name = "value" });//simple test JSON data
    string decodedToken = Base64URLEncode(header) + "." + Base64URLEncode(payload);
    //eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidmFsdWUifQ
    byte[] privateKeyBytes = Convert.FromBase64String(privateKey);
    using (ECDsa ecdsa = ECDsa.Create())
    {
        ecdsa.ImportECPrivateKey(privateKeyBytes, out _);
        string encodedToken = JWT.Encode(decodedToken, ecdsa, JwsAlgorithm.ES384);
        //eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.ZXlKaGJHY2lPaUpGVXpNNE5DSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnVZVzFsSWpvaWRtRnNkV1VpZlE.kYj0M2GNC5w9oRrIVcHJ9dSQLbOEjNjxd61zSXD5iz0nBRRWMWyxj2l1DAhKPa_hpaFUscuubCzYe_W1SKpo3s06on-hYnICgQH4fVoAwZxiM_N4W761jecOExfivztn
        return encodedToken;
    }
}

private static string Base64URLEncode(JObject jObject)
{
    string jsonString = jObject.ToString(Formatting.None);
    byte[] jsonBytes = Encoding.UTF8.GetBytes(jsonString);
    string escapedBase64 = Convert.ToBase64String(jsonBytes).TrimEnd('=').Replace('+', '-').Replace('/', '_');
    return escapedBase64;
}

更新

謝謝你到目前為止的答案。 我想我已經接近了,但是 jwt.io 仍然說,“無效簽名”,即使我已經粘貼了公鑰。 使用以下信息,我希望有人能告訴我為什么說我的簽名無效。

I've generated a temporary private key just for the purpose of debugging this situation on stackoverflow.com: MIGkAgEBBDBywQ7LVcyOGzxJ0Tpjpww2zUZbbtb3WVm4A3uv7ho31jJzQRYTpSqR7+ORAdoxmamgBwYFK4EEACKhZANiAASG50vW1r/O1XmUbTBb6yx1YSABh1USA6MJ8HJnYJ58tjGGVPL88a6Z1gOUlAsHtNhL44PhnTNTNNFdaH2Z41yn7oZmBhuon0vuUNFic2HDpfa/uFwRUAmhSBQz8hu+980=

I initialized an instance of ecdsa with my private key and generated a public key with Convert.ToBase64String(ecdsa.ExportSubjectPublicKeyInfo()) : MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEhudL1ta/ztV5lG0wW+ssdWEgAYdVEgOjCfByZ2CefLYxhlTy/PGumdYDlJQLB7TYS+OD4Z0zUzTRXWh9meNcp+6GZgYbqJ9L7lDRYnNhw6X2v7hcEVAJoUgUM/IbvvfN

這是更新的代碼:

private static string GetSignedEncodedToken(string privateKey)
{
    JObject payload = JObject.FromObject(new { name = "value" });//simple test JSON data
    string payloadString = payload.ToString(Formatting.None);
    byte[] privateKeyBytes = Convert.FromBase64String(privateKey);
    using (ECDsa ecdsa = ECDsa.Create())
    {
        ecdsa.ImportECPrivateKey(privateKeyBytes, out _);
        string signedEncodedToken = JWT.Encode(payloadString, ecdsa, JwsAlgorithm.ES384);
        return signedEncodedToken;
    }
}

And here is the signed encoded token: eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.ew0KICAibmFtZSI6ICJ2YWx1ZSINCn0.KpJAgc3-yaoGmHGAXHOeH3BPgpxdBRm461yWia60dgjuQHG5iLnwLQtQgdZtsHnI-bEK_wdmvu85ZrF7n-TdWiFb4FQxGeLBeeRfnMLJhKfInu_7MYEWPS2Ohm4yBAqg

更新解決方案

正如 jps 所提到的,我需要用“-----BEGIN PUBLIC KEY-----”和“-----END PUBLIC KEY-----”來包裝我的公鑰。 然后 jwt.io 顯示“簽名已驗證”。

您在這里調用的decodedToken基本上已經是沒有簽名的編碼令牌。 function JWT.Encode采用第一個參數並重復您已經手動執行的操作,即它創建一個 base64url 編碼的 header 和有效負載,然后為您簽名。 您不需要創建自己的 header 也不需要關心 base64url 編碼。

因此,您只需要在那里傳遞您的payload (不是 base64 編碼的)。 結果是一個簽名的令牌。

並且 jwt.io 顯示“無效簽名”,因為您可能沒有將公鑰傳遞給右欄中的“公鑰”字段。 在不知道公鑰的情況下,無法驗證簽名。

當您在那里粘貼公鑰時,確保它具有 header 和頁腳行-----BEGIN PUBLIC KEY----- -----END PUBLIC KEY----- ,然后驗證應該可以正常工作。

您提供的令牌,我在jwt.io調試器中使用了相同的令牌,可以看到幾個問題:

eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.ZXlKaGJHY2lPaUpGVXpNNE5DSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnVZVzFsSWpvaWRtRnNkV1VpZlE.kYj0M2GNC5w9oRrIVcHJ9dSQLbOEjNjxd61zSXD5iz0nBRRWMWyxj2l1DAhKPa_hpaFUscuubCzYe_W1SKpo3s06on-hYnICgQH4fVoAwZxiM_N4W761jecOExfivztn

以下是解碼的詳細信息:

Header(正確):

{
  "alg": "ES384",
  "typ": "JWT"
}

有效載荷(不正確):

"eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidmFsdWUifQ"

由於 Payload 預計為 Json,而不是Base64Encoded字符串。 您應該能夠對其進行修改以生成新的令牌。

現在主要錯誤:

對於解碼調試器肯定需要公鑰,它可以與私鑰匹配,如果您使用非對稱加密,如果您使用Symmetric encryption ,那么兩個密鑰將相同。

或者,您還可以添加私鑰以使用修改后的算法或有效負載生成新令牌。

以編程方式,您可以查看詳細信息:

  1. 您正在提供正確的公鑰以匹配私鑰
  2. 您以編程方式將 Base64String 轉換為 Json。 這對於JWT調試器是不可行的

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM