nacos icon indicating copy to clipboard operation
nacos copied to clipboard

Accurately refresh the client's access token

Open lucky8987 opened this issue 1 year ago • 9 comments

Is your feature request related to a problem? Please describe. If the user updates the nacos.core.auth.plugin.nacos.token.secret.key parameter in the application, the generated access tokens will need to wait for the next cycle before being refreshed, with a refresh interval of nacos.core.auth.plugin.nacos.token.expire.seconds - (nacos.core.auth.plugin.nacos.token.expire.seconds/10); During this period, when the client calls Nacos related interfaces, it will prompt: Invalid signature. The reason is that the server has already updated the key, causing the signature verification to fail.

如果用户更新了application 中的 nacos.core.auth.plugin.nacos.token.secret.key 参数,针对已经产生的accessToken需要等待下一个周期才会进行刷新,刷新间隔 = nacos.core.auth.plugin.nacos.token.expire.seconds - (nacos.core.auth.plugin.nacos.token.expire.seconds / 10);在这期间客户端调用Nacos相关接口将会提示:Invalid signature 原因是服务端已经更新key导致签名校验不通过。

Describe the solution you'd like Judge the server response code in the 'nacose client' code, such as code=403; In this scenario, it means that the Nacos server has adjusted the auth key, which can trigger a user to log in again to refresh the access token. This way, the client will obtain the latest access token.

nacose-client代码中对服务端响应code进行判断,如code=403;这种场景下意味着Nacos服务端调整了auth key,那么可以触发一次用户重新登录来刷新accessToken,这样客户端将获取到最新的accessToken。

private <T extends Response> T requestToServer(AbstractNamingRequest request, Class<T> responseClass)
            throws NacosException {
        Response response = null;
        try {
            request.putAllHeader(
                    getSecurityHeaders(request.getNamespace(), request.getGroupName(), request.getServiceName()));
            response = requestTimeout < 0 ? rpcClient.request(request) : rpcClient.request(request, requestTimeout);
            if (ResponseCode.SUCCESS.getCode() != response.getResultCode()) {
                // TODO If the 403 login operation is triggered, refresh the accessToken of the client
                throw new NacosException(response.getErrorCode(), response.getMessage());
            }
            if (responseClass.isAssignableFrom(response.getClass())) {
                return (T) response;
            }
            NAMING_LOGGER.error("Server return unexpected response '{}', expected response should be '{}'",
                    response.getClass().getName(), responseClass.getName());
            throw new NacosException(NacosException.SERVER_ERROR, "Server return invalid response");
        } catch (NacosException e) {
            recordRequestFailedMetrics(request, e, response);
            throw e;
        } catch (Exception e) {
            recordRequestFailedMetrics(request, e, response);
            throw new NacosException(NacosException.SERVER_ERROR, "Request nacos server failed: ", e);
        }
    }

Describe alternatives you've considered We encountered an issue when upgrading Nacos from version 2.2.3 to 2.4.2, where the client reconnecting to Nacos prompted: Invalid signature; After investigation, we found that versions 2.3. x and later have made adjustments to the base64 of the auth key, which led to this issue. For details, please refer to the issue: https://github.com/alibaba/nacos/pull/12434 The official suggestion for this issue is to adjust the Nacos parameter `nacos.core.auth.plugin.nacos.token.expire.seconds' to shorten the expiration time, but this will make the refresh frequency very frequent and require restarting the original service before upgrading, which is not very elegant.

我们在将Nacos由2.2.3版本升级到2.4.2时遇到了一个问题,这个问题是客户端重连Nacos提示:Invalid signature;经过排查我们发现2.3.x以后的版本针对auth key的base64进行过调整,导致了这个问题的出现,详情参考issue:https://github.com/alibaba/nacos/pull/12434 对于这个问题,官方的建议是调整Nacos参数nacos.core.auth.plugin.nacos.token.expire.seconds 来缩短过期时间,但是这样会将刷新变得很频繁,而且需要先重启原有服务再升级,这样不太优雅。

Additional context Add any other context or screenshots about the feature request here.

lucky8987 avatar Oct 11 '24 13:10 lucky8987

welcome PR

KomachiSion avatar Oct 12 '24 06:10 KomachiSion

但是只判断403,也可能会导致频繁访问,可以判断403的话逐渐延长重试周期的方案。

KomachiSion avatar Oct 12 '24 06:10 KomachiSion

顺便将访问异常后延长重试周期也一起添加了吧。

KomachiSion avatar Oct 12 '24 06:10 KomachiSion

@ i will solve it , please assign to me @

Sitosoym avatar Oct 13 '24 17:10 Sitosoym

感觉判断403的话不仅包含了上文中auth key改变的情况,应该还包含了用户不存在/密码错误等情况,范围会不会太广了从而导致无效刷新?看上去判断auth key改变的情况 只需要符合 Invalid signature 这个提示就行,且只需重新登录一次刷新一下token就好了?

Sitosoym avatar Oct 13 '24 17:10 Sitosoym

感觉判断403的话不仅包含了上文中auth key改变的情况,应该还包含了用户不存在/密码错误等情况,范围会不会太广了从而导致无效刷新?看上去判断auth key改变的情况 只需要符合 Invalid signature 这个提示就行,且只需重新登录一次刷新一下token就好了?

如果要更多信息, 可能连login接口都需要修改了,改动会比较大, 短期可以考虑判断403之后, 逐渐增加重试间隔。

注册中心的ServiceInfoUpdater中有类似的递增机制,可以考虑参考。

KomachiSion avatar Oct 16 '24 09:10 KomachiSion

感觉判断403的话不仅包含了上文中auth key改变的情况,应该还包含了用户不存在/密码错误等情况,范围会不会太广了从而导致无效刷新?看上去判断auth key改变的情况 只需要符合 Invalid signature 这个提示就行,且只需重新登录一次刷新一下token就好了?

如果能够基于现有的逻辑判断Invalid signature 也行, 但是其他的场景最好也添加一下报错(不一定只403)时,逐渐增加重试间隔。

KomachiSion avatar Oct 16 '24 09:10 KomachiSion

好的,但是我看重试的操作有专门的NamingGrpcRedoService来完成了,默认是3秒一次重试登录,但会在登录前判断一下token在快要expire的时候才真正调服务端的接口重新获取新的token,所以在issue作者更新服务端auth key的时候客户端会不停的报Invalid signature。 pr当中从login接口中抽取出立即登录且无需验证上次token刷新时间的部分作为新的接口,以此在requestToServer中接收到Invalid signature时触发一次强制重新登录。 复现了issue作者的情况,改动之后解决了问题。

Sitosoym avatar Oct 16 '24 14:10 Sitosoym

感觉判断403的话不仅包含了上文中auth key改变的情况,应该还包含了用户不存在/密码错误等情况,范围会不会太广了从而导致无效刷新?看上去判断auth key改变的情况 只需要符合 Invalid signature 这个提示就行,且只需重新登录一次刷新一下token就好了?

基于Invalid signature 的提示判断过于狭隘了,因为目前auth抽取出spi插件实现,非nacos认证插件无法命中client端刷新机制;其他场景可能也要考虑下,我认为理想的状态就是只改动client段不要改动server段来解决这个问题,server端不用升级。

lucky8987 avatar Oct 17 '24 04:10 lucky8987

m

chenzhiguo avatar Nov 07 '24 02:11 chenzhiguo

这个 feature 很危险, login 这个接口很消耗性能!担心大量的login 一起过来,把server的cpu 搞死了。

目前服务端如果换token,可以临时关闭 6小时鉴权。

dongyun-coder avatar Aug 12 '25 10:08 dongyun-coder