【问题标题】:Cannot decode token in python created in ASP.NET using secret无法使用秘密解码在 ASP.NET 中创建的 python 中的令牌
【发布时间】:2020-11-26 10:53:37
【问题描述】:

使用以下代码在 .Net 中创建秘密

var key = new byte[32];
RNGCryptoServiceProvider.Create().GetBytes(key);
var base64Secret = TextEncodings.Base64Url.Encode(key)
Audience newAudience = new Audience { ClientId = clientId, Base64Secret = base64Secret, Name = name };

使用以下代码在 .Net 中创建令牌

string symmetricKeyAsBase64 = audience.Base64Secret;    
var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
var signingKey = new HmacSigningCredentials(keyByteArray);
var issued = data.Properties.IssuedUtc;
var expires = data.Properties.ExpiresUtc;
var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey);

以上代码成功创建了需要在python中解码的token:

秘密是XYZ,它被生成并存储在数据库中。在存储到数据库之前,秘密使用TextEncodings.Base64Url.Encode 进行编码。我尝试通过添加“=”

来解码 python 中的密钥
base64.urlsafe_b64decode("XYZ=")

我还尝试使用以下方法添加双等号“==”

base64.b64decode("XYZ==")

最后我尝试了以上两种方法来解码秘密并在jwt.decode()中使用它

jwt.decode(token, secret, algorithms=['HS256'])

一切都没有奏效。

令牌看起来像

HEADER:ALGORITHM & TOKEN TYPE

{
  "typ": "JWT",
  "alg": "HS256"
}
PAYLOAD:DATA

{
  "unique_name": "devuser",
  "sub": "devuser",
  "role": [
    "Manager",
    "Supervisor"
  ],
  "iss": "https://xxxxxxx.azurewebsites.net",
  "aud": "6A00574AE5514C1C90D2D5332FEF78F9",
  "exp": 1596636265,
  "nbf": 1596634465
}

**VERIFY SIGNATURE**
HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
)

【问题讨论】:

  • 那么现在有什么问题? 所有的事情都不起作用。 - 这不是一个足够的错误描述。又是填充错误吗?至少您应该从旧问题中的链接重复项中了解到,base64 字符串的长度应该可以被 4 整除,因此添加两个 '=' 没有意义。上次我还检查了当你有一个用 base64 编码的秘密签名的 JWT 时你的 python 代码是否正常工作。所以也许 C# 方面是问题所在。显示您的 C# 生成的令牌。
  • 当我使用该令牌时,使用给定的秘密(用一个“=”填充)和此代码:decoded = jwt.decode(token, secret) 我收到ExpiredSignatureError('Signature has expired') 错误。如果我尝试使用另一个令牌,使用相同的密钥制作并且在 jwt.io 上未过期,则解码工作正常。
  • 所以您出于安全考虑编辑问题和答案,但使用从教程中复制的秘密,可以在more than 250 times on google找到?

标签: python c# jwt base64 pyjwt


【解决方案1】:

首先秘密需要填充。尽管 Base64Url 编码通常为does not require padding,Python Base64 解码器需要它。 所以秘诀是:

XYZ=

(填充到 44 个字符)。

没有填充你会得到:

binascii.Error: 不正确的填充

然后您的令牌包含audience claim,PyJWT 必须验证受众。

引用上述链接文档:

如果处理该声明的主体在此声明存在时未使用“aud”声明中的值标识自己,则必须拒绝 JWT。

如果您没有将有效受众作为参数传递给decode,您将收到异常:

InvalidAudienceError('无效的观众')

如果你通过了有效的观众,就像在这个例子中:

import jwt
import base64

token = "abc"

secret = base64.urlsafe_b64decode("XYZ=")
allowed_audience = "6A00574AE5514C1C90D2D5332FEF78F9"

decoded = jwt.decode(token, secret, audience = allowed_audience)
print(decoded)

效果很好。

【讨论】:

  • 是的,这行得通。所以我错过了添加观众:) 谢谢
  • 终于成功了,乐于助人。但是为什么您没有任何错误消息或异常?
  • 我直接在 Postman 中使用 try 进行检查,但没有引发错误。说if decoded : token valid else: Token invalid
  • 我直接在空闲状态下工作,所以我看到了每一个异常。让生活更轻松。
猜你喜欢
  • 2019-07-05
  • 1970-01-01
  • 2015-02-21
  • 2015-10-02
  • 2020-06-08
  • 2022-11-22
  • 1970-01-01
  • 2014-10-29
  • 2012-04-28
相关资源
最近更新 更多