简体   繁体   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”

Using the below code, I am able to build a decoded JSON Web Token ( decodedToken ).使用下面的代码,我可以构建一个解码的 JSON Web 令牌( decodedToken )。 When I paste it into the debugger on https://jwt.io , the header and payload are correctly shown on the right.当我将其粘贴到https://jwt.io上的调试器中时,header 和有效负载正确显示在右侧。 But when I paste the encoded token ( encodedToken ) into the debugger, I get this message:但是,当我将编码的令牌 ( encodedToken ) 粘贴到调试器中时,我会收到以下消息:

Looks like your JWT payload is not a valid JSON object.看起来您的 JWT 有效负载不是有效的 JSON object。 JWT payloads must be top level JSON objects as per https://tools.ietf.org/html/rfc7519#section-7.2根据https://tools.ietf.org/html/rfc7519#section-7,JWT有效负载必须是顶级 JSON 对象。

It also says, "Invalid Signature," in big red letters at the bottom.它还在底部用大红色字母表示“无效签名”。

In addition, when using the encoded token, the header area shows my decoded header, and the payload area shows my entire decoded token .此外,使用编码令牌时,header 区域显示我解码的 header,有效负载区域显示我的整个解码令牌 So somehow jwt.io is successfully decoding the JWT.所以 jwt.io 以某种方式成功解码了 JWT。 But it shouldn't be trying to parse the JSON of the entire decoded token as a single unit.但它不应该尝试将整个解码令牌的 JSON 解析为一个单元。 It should be trying to parse the JSON of the header and payload portions separately.它应该尝试分别解析 header 的 JSON 和有效负载部分。

I would like to know why jwt.io can't quite my payload of my encoded token.我想知道为什么 jwt.io 不能完全了解我的编码令牌的有效负载。 The values of both the decodedToken and encodedToken are shown as comments in the below source code. decodedTokenencodedToken的值在下面的源代码中显示为注释。 Thank you.谢谢你。

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

Update更新

Thank you for the answers so far.谢谢你到目前为止的答案。 I think I'm close, but jwt.io still says, "Invalid Signature," even though I've pasted in the public key.我想我已经接近了,但是 jwt.io 仍然说,“无效签名”,即使我已经粘贴了公钥。 Using the below information, I'm hoping someone can tell me why my signature is said to be invalid.使用以下信息,我希望有人能告诉我为什么说我的签名无效。

I've generated a temporary private key just for the purpose of debugging this situation on stackoverflow.com: MIGkAgEBBDBywQ7LVcyOGzxJ0Tpjpww2zUZbbtb3WVm4A3uv7ho31jJzQRYTpSqR7+ORAdoxmamgBwYFK4EEACKhZANiAASG50vW1r/O1XmUbTBb6yx1YSABh1USA6MJ8HJnYJ58tjGGVPL88a6Z1gOUlAsHtNhL44PhnTNTNNFdaH2Z41yn7oZmBhuon0vuUNFic2HDpfa/uFwRUAmhSBQz8hu+980= 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 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

Here is the updated code:这是更新的代码:

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 And here is the signed encoded token: eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.ew0KICAibmFtZSI6ICJ2YWx1ZSINCn0.KpJAgc3-yaoGmHGAXHOeH3BPgpxdBRm461yWia60dgjuQHG5iLnwLQtQgdZtsHnI-bEK_wdmvu85ZrF7n-TdWiFb4FQxGeLBeeRfnMLJhKfInu_7MYEWPS2Ohm4yBAqg

Solution to Update更新解决方案

As mentioned by jps, I needed to wrap my public key with "-----BEGIN PUBLIC KEY-----" and "-----END PUBLIC KEY-----".正如 jps 所提到的,我需要用“-----BEGIN PUBLIC KEY-----”和“-----END PUBLIC KEY-----”来包装我的公钥。 Then jwt.io shows, "Signature Verified."然后 jwt.io 显示“签名已验证”。

What you're calling decodedToken here is basically already an encoded token without signature.您在这里调用的decodedToken基本上已经是没有签名的编码令牌。 The function JWT.Encode takes the first parameter and repeats what you already did manually, ie it creates a base64url encoded header and payload for you and then signs the token. function JWT.Encode采用第一个参数并重复您已经手动执行的操作,即它创建一个 base64url 编码的 header 和有效负载,然后为您签名。 You don't need to create your own header and you don't need to care about base64url encoding.您不需要创建自己的 header 也不需要关心 base64url 编码。

Therefore you just need to pass your payload (not base64 encoded) there.因此,您只需要在那里传递您的payload (不是 base64 编码的)。 The result is a signed token.结果是一个签名的令牌。

And jwt.io shows "invalid signature" because you probably didn't pass the public key to the "public key" field in the right column.并且 jwt.io 显示“无效签名”,因为您可能没有将公钥传递给右栏中的“公钥”字段。 Without knowing the public key, the signature can't be verified.在不知道公钥的情况下,无法验证签名。

When you paste a public key there, make sure it has the header and footer lines -----BEGIN PUBLIC KEY----- -----END PUBLIC KEY----- , then verification should work fine.当您在那里粘贴公钥时,确保它具有 header 和页脚行-----BEGIN PUBLIC KEY----- -----END PUBLIC KEY----- ,然后验证应该可以正常工作。

Token that you have provided, I used the same in jwt.io debugger and can see couple of issues:您提供的令牌,我在jwt.io调试器中使用了相同的令牌,可以看到几个问题:

eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.ZXlKaGJHY2lPaUpGVXpNNE5DSXNJblI1Y0NJNklrcFhWQ0o5LmV5SnVZVzFsSWpvaWRtRnNkV1VpZlE.kYj0M2GNC5w9oRrIVcHJ9dSQLbOEjNjxd61zSXD5iz0nBRRWMWyxj2l1DAhKPa_hpaFUscuubCzYe_W1SKpo3s06on-hYnICgQH4fVoAwZxiM_N4W761jecOExfivztn

Following are decoded details:以下是解码的详细信息:

Header (which is correct): Header(正确):

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

Payload (which is not correct):有效载荷(不正确):

"eyJhbGciOiJFUzM4NCIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoidmFsdWUifQ"

Since Payload is expected to be Json, not a Base64Encoded string.由于 Payload 预计为 Json,而不是Base64Encoded字符串。 You shall be able to modify it to generate a new Token.您应该能够对其进行修改以生成新的令牌。

Now Main Error:现在主要错误:

For decoding debugger surely needs Public Key, which can match with Private Key, that's in case you use Asymmetric encryption, in case you use Symmetric encryption then both keys will be same.对于解码调试器肯定需要公钥,它可以与私钥匹配,如果您使用非对称加密,如果您使用Symmetric encryption ,那么两个密钥将相同。

Optionally you can also add the Private Key to generate the new token with modified algorithm or payload.或者,您还可以添加私钥以使用修改后的算法或有效负载生成新令牌。

Programmatically you are able to see the details:以编程方式,您可以查看详细信息:

  1. You are supplying the right Public key to match the Private Key您正在提供正确的公钥以匹配私钥
  2. You convert Base64String to Json programmatically.您以编程方式将 Base64String 转换为 Json。 which is not feasible for JWT debugger这对于JWT调试器是不可行的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM