KEYCLOAK - 刷新/更新令牌无效

16

我有一个单页应用程序,使用Angularjs构建,并与Keycloak集成以实现身份验证和授权

我能够登录我的应用程序,获取已登录用户的角色等信息。但是每次刷新令牌调用时,它始终返回到我的else情况,并使用户退出应用程序。尽管令牌有效时间设置得非常高。

如果用户打开了应用程序,我需要更新令牌。如果令牌失效或过期,我需要注销用户。if (refreshed)始终返回false。

下面是我正在使用的代码片段。

var __env = {};

        Object.assign(__env, window.__env);

        var keycloakConfig = {
            "url" : __env.keycloakUrl,
            "realm" : __env.keycloakRealm,
            "clientId" : __env.keycloakClientId,
            "credentials" : {
            "secret" : __env.keycloakSecret
            }
        };
var keycloak = Keycloak(keycloakConfig);
        keycloak.init({
            onLoad : 'login-required'
        }).success(function(authenticated) {
                 if(authenticated){                  
                        keycloak.loadUserInfo().success(function(userInfo) {
                        bootstrapAngular(keycloak, userInfo, roles);
                    });
            }
        });

function bootstrapAngular(keycloak, userInfo, roles) {
        angular.module('myApp').run(
                function($rootScope, $http, $interval, $cookies) {
                    var updateTokenInterval = $interval(function() {
                        // refresh token if it's valid for less then 15 minutes
                    keycloak.updateToken(15).success(
                                function(refreshed) {
                                    if (refreshed) {
                                        $cookies.put('X-Authorization-Token',
                                                keycloak.token);
                                    }else{
                                        $rootScope.logoutApp();
                                    }
                                });
                    }, 600000);
                    updateTokenInterval;
                    $cookies.put('X-Authorization-Token', keycloak.token);

                    $rootScope.logoutApp = function() {
                        $cookies.remove('X-Authorization-Token');
                        $interval.cancel(updateTokenInterval);
                        keycloak.logout();
                    };
    }
}

1
你有类似的问题吗?你找到解决方案了吗? - Atropo
6个回答

16

我在API文档中找不到解释,但是keycloak.updateToken()函数的timeout参数以为单位表示,而不是分钟。

因此,如果服务器上的访问令牌生命周期处于默认值5分钟,则应使用小于300秒的值。 我通过一些实验学到了这一点。

//Update the token when will last less than 3 minutes
keycloak.updateToken(180)

顺便说一下,我建议您使用寿命长于5分钟的令牌

在您的代码中,您从未看到令牌被刷新,因为在15秒的时间窗口内未触发刷新。


7
如果您需要强制刷新令牌(例如更新其中的权限),可以使用 updateToken(-1)。请勿滥用此功能... - Dan Manastireanu
如果我们多次请求 updateToken,Keycloak 会维护这些调用的队列,并且只处理第一个 updateToken 请求。每当第一个 updateToken 的响应被接收时,它立即返回其响应以处理队列中所有剩余的 updateToken 请求。 - Chetan Goyal

9

(refreshed)仅在您的令牌未过期时返回false。 因此,您正在尝试在令牌尚未过期时刷新令牌

在您使用的Keycloak领域中将“访问令牌寿命”设置为1分钟,然后尝试以下代码以再次检查刷新状态。

keycloak.onTokenExpired = ()=>{
            console.log('expired '+new Date());
            keycloak.updateToken(50).success((refreshed)=>{
                if (refreshed){
                    console.log('refreshed '+new Date());
                }else {
                    console.log('not refreshed '+new Date());
                }
            }).error(() => {
                 console.error('Failed to refresh token '+new Date());
            });
            }

2
所以你正在尝试在令牌尚未过期时刷新它。是的,就是这样!谢谢。 - Tazo leladze
1
你能解释一下 updateToken 的 min validity 参数(在这个例子中是 50)是什么意思吗?在我的情况下,我有一个 WebSocket 连接,当令牌过期时,连接会关闭并重试,重试,重试...那么我可以说令牌已经正确地刷新并且连接已经打开了吗? - Tazo leladze
如果令牌在minValidity秒内过期(minValidity是可选的,如果未指定,则使用5),则刷新令牌。如果启用了会话状态iframe,则还会检查会话状态。这就是文档所说的。 - Charith Jayasanka
在初始化keycloak之前必须添加tokenExpired。 - PPr

4
我来看一下他们的示例代码:

我来看一下他们的示例代码:

        /**
     * If the token expires within `minValidity` seconds, the token is refreshed.
     * If the session status iframe is enabled, the session status is also
     * checked.
     * @returns A promise to set functions that can be invoked if the token is
     *          still valid, or if the token is no longer valid.
     * @example
     * ```js
     * keycloak.updateToken(5).success(function(refreshed) {
     *   if (refreshed) {
     *     alert('Token was successfully refreshed');
     *   } else {
     *     alert('Token is still valid');
     *   }
     * }).error(function() {
     *   alert('Failed to refresh the token, or the session has expired');
     * });
     */

我认为你的令牌仍然有效,这就是为什么updateToken返回false的原因。


1
keycloak.onAuthSuccess = function() { alert('authenticated'); }

keycloak.onTokenExpired = function () {
            keycloak.updateToken(5)
            .then(function (refreshed) {
                if (refreshed) {
                    alert('Token refreshed');
                  // write any code you required here
                } else {
                    alert('Token is still valid now');
                }
            }).catch(function () {
                alert('Failed to refresh the token, or the session has expired');
            }); }
            keycloak.init({ onLoad: 'login-required' }).then(function (authenticated) {..... }

如何在客户端JavaScript中更新Keycloak令牌,当令牌过期时,请参考以下链接:https://github.com/keycloak/keycloak-documentation/blob/main/securing_apps/topics/oidc/javascript-adapter.adoc该适配器支持为某些事件设置回调侦听器。请记住,在调用init函数之前必须设置这些(例如onTokenExpired、onAuthSuccess、onAuthRefreshSuccess等)。 - PPr

0
在标准流程中,我注意到令牌过期时间来自访问令牌生命周期,而刷新令牌过期时间来自SSO会话空闲时间。建议访问令牌生命周期应该比SSO超时时间短。难道不应该反过来吗? 此外,在“高级设置”下的“客户端设置”选项卡中可以覆盖访问令牌生命周期。

-1

我正在使用同样的东西,它并没有解决我的问题,实际上它根本没有刷新令牌。 - Ankur Singhal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接