Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Default JWT plugin is not forward compatible with the secretKey of older versions of Nacos #10930

Closed
xyohn opened this issue Aug 8, 2023 · 5 comments
Labels
help wanted Extra attention is needed plugin

Comments

@xyohn
Copy link
Contributor

xyohn commented Aug 8, 2023

默认JWT插件无法向前兼容旧版本Nacos的secretKey

The old version of Nacos(<2.2.1) uses the JWT parsing capability provided by the jjwt component, and the new version (>=2.2.1) provides the self-developed JWT parsing capability provided by the Feature of #9859, but there are differences in the processing logic of secretKey between the two.
旧版本的 Nacos(<2.2.1) 使用的是 jjwt 组件提供的JWT解析能力,新版本(>=2.2.1)为 #9859 的 Feature 提供的自开发JWT解析能力,但两者对于 secretKey 的处理逻辑存在差异。

The old version uses io.jsonwebtoken.io.Decoder#decode in the jjwt component to decode Base64 strings into byte arrays, which is compatible with ** non-compliant Base64 strings ** (to intercepts the incoming string ).
旧版本使用的是 jjwt 组件中 io.jsonwebtoken.io.Decoder#decode 完成Base64字符串解码成byte数组,其兼容了不合规的 Base64 字符串,会对传入的字符串进行截取。

In the new version,java.util.Base64.Decoder#decode(java.lang.String) is used to decode Base64 strings into byte arrays. IllegalArgumentException will be thrown for nonstandard Base64 strings. In the com.alibaba.nacos.plugin.auth.impl.jwt.NacosJwtParser constructor, this exception is handled by obtaining the byte array of secretKey strings.
而新版本使用的是 java.util.Base64.Decoder#decode(java.lang.String) 完成 Base64 字符串解码成 byte 数组,对于不合规的 Base64 字符串会抛出 IllegalArgumentException 的异常,在 com.alibaba.nacos.plugin.auth.impl.jwt.NacosJwtParser 构造方法中,对该异常的处理方式是获取 secretKey 字符串的 byte 数组。

The old version of Nacos intercepts the nonstandard Base64 string, while the new version of Nacos obtains the byte array of the string. The logical inconsistency between the two will cause the Invalid signature error to occur when the old version of Nacos is upgraded to the new version of Nacos. If the nonstandard Base64 string is used, even if the secretKey is consistent with the old version configuration, the client cannot call the server service normally. The Client needs to obtain the Token again before it can be used normally.
旧版本 Nacos 对于不合规 Base64 字符串采用截取的方式,而新版本 Nacos 采用获取该字符串 byte 数组,两者逻辑的不一致会导致旧版本的 Nacos 在升级到新版本 Nacos 时,如若使用不合规的Base64字符串,即便密钥与旧版本配置一致,也可能会产生 Invalid signature 的错误,造成 Client 端无法正常调用 Server 端服务。Client 需重新获取 Token 后才能正常使用。

As for the setting of secretKey, the old version of Nacos documentation (<2.2.1) does not specify that it needs to be set to Base64-encoded string (when the new Nacos documentation prompts for a custom key, it is recommended to set it to Base64-encoded string).
关于 secretKey 密钥的设置,在旧版本 Nacos 文档(<2.2.1)中并未明确需要设置为 Base64 编码的字符串(新 Nacos 文档提示为自定义密钥时,推荐设置为 Base64 编码的字符串)

The original default secretKey is also not a Base64 encoded value intuitively understood, and the secretKey is also a nonstandard Base64 string in essence. In the logic of the new Nacos version, it will enter the logic of obtaining the byte array of the secretKey string. This issue also occurs when users upgrade from an older version of Nacos to a newer version of Nacos when using the default secretKey.
原先的默认公开密钥(SecretKey0...9)也非直觉上理解的 Base64 编码值,且该公开密钥实质上也为不合规的 Base64 字符串,在新 Nacos 版本的逻辑中会进入到获取 secretKey 字符串的 byte 数组的逻辑;用户如若使用默认公开密钥从旧版本 Nacos 升级到新版本 Nacos,亦会出现该问题

20230808-183523

Considering that the secretKey is compatible with the old version of Nacos configuration, it is recommended that the new version of Nacos JWT authentication plugin refer to the implementation logic of jjwt component in the Base64 decoding processing logic of the secretKey, so as to ensure that the old version of Nacos can be upgraded to the new version without feeling the client and better complete the smooth upgrade.
考虑到兼容旧版本 Nacos 配置的 secretKey,建议新版本的 Nacos JWT 鉴权插件,在 secretKey 的 Base64 解码处理逻辑上参考 jjwt 组件的实现逻辑,以保证旧版本 Nacos 升级新版本时,能对客户端无感,更好的完成平滑升级

Describe the bug

when the old version of Nacos is upgraded to the new version of Nacos,the client cannot call the server service normally. The Client needs to obtain the Token again before it can be used normally.

Expected behavior

when the old version of Nacos is upgraded to the new version of Nacos,the client can call the server service normally.An Invalid signature error will not occur.

Actually behavior

an Invalid signature will occur.

How to Reproduce
Steps to reproduce the behavior:

  1. Prerequisite, have an older version(<2.2.1) of Nacos cluster,and the secreKey is nonstandard.(eg. SecretKey012345678901234567890123456789012345678901234567890123456789 or MLFvWOP3KbIeX06J9i8nANslzxD7kfa2TrBCthojUpwZR1GmEdYScHyV5u4QqgPKcrEg0 )
  2. Upgrade one of them with the same secretKey configuration

Desktop (please complete the following information):

  • OS: [e.g. Centos]
    Centos
  • Version [e.g. nacos-server 1.3.1, nacos-client 1.3.1]
    Nacos 2.0.3 upgrade to 2.2.3
  • Module [e.g. naming/config]
    auth
  • SDK [e.g. original, spring-cloud-alibaba-nacos, dubbo]

Additional context
Add any other context about the problem here.

xyohn added a commit to xyohn/nacos that referenced this issue Aug 8, 2023
xyohn added a commit to xyohn/nacos that referenced this issue Aug 8, 2023
xyohn added a commit to xyohn/nacos that referenced this issue Aug 8, 2023
@KomachiSion KomachiSion added plugin help wanted Extra attention is needed labels Aug 10, 2023
@KomachiSion
Copy link
Collaborator

@YunWZ help review this issue?

@YunWZ
Copy link
Contributor

YunWZ commented Aug 14, 2023

LGTM

@xyohn
Copy link
Contributor Author

xyohn commented Aug 18, 2023

LGTM

For this,I have opened a pull request(#10931) and could you help to review it? thanks

@changhr2013
Copy link

并不需要参考 jjwt 整个改动 base64 解码的逻辑,合法的 base64 字符串长度都要满足是 4 的倍数,只要将原字符串对 4 取余,解码时丢弃掉末尾的余数位字符串即可达到同样的效果。

byte[] decode;
try {
    decode = Base64.getDecoder().decode(base64edKey);
} catch (IllegalArgumentException e) {
    decode = base64edKey.getBytes(StandardCharsets.US_ASCII);
}

变更为:

int remainder = base64edKey.length() % 4;
String legalBase64Key = remainder == 0 ? base64edKey : base64edKey.substring(0, base64edKey.length() - remainder);
byte[] decode = Base64.getDecoder().decode(legalBase64Key);

@xyohn
Copy link
Contributor Author

xyohn commented Aug 21, 2023

并不需要参考 jjwt 整个改动 base64 解码的逻辑,合法的 base64 字符串长度都要满足是 4 的倍数,只要将原字符串对 4 取余,解码时丢弃掉末尾的余数位字符串即可达到同样的效果。

byte[] decode;
try {
    decode = Base64.getDecoder().decode(base64edKey);
} catch (IllegalArgumentException e) {
    decode = base64edKey.getBytes(StandardCharsets.US_ASCII);
}

变更为:

int remainder = base64edKey.length() % 4;
String legalBase64Key = remainder == 0 ? base64edKey : base64edKey.substring(0, base64edKey.length() - remainder);
byte[] decode = Base64.getDecoder().decode(legalBase64Key);

是的,你说的在理。
另外 jjwt 的 Base64 实现里还对首尾的非Base64字符做了过滤,如果实现了取余和首尾非 Base64 字符过滤的话,再调用java.util.Base64.Decoder#decode(java.lang.String)得到上的结果应该是一致的

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Extra attention is needed plugin
Projects
None yet
Development

No branches or pull requests

4 participants