我对刷新令牌有一个问题:在我看来,当我得到一个新的正常令牌时,它没有被更新。我已将令牌有效期设置为5分钟。刷新令牌过期时间必须为40分钟。这是一个公司keycloak服务器,我没有管理它,他们只能为令牌设置应用程序的时间,而不能为刷新令牌设置时间。每次使用updateToken时,我都调试了正常token和刷新token。两者都被刷新了。但是当我达到40分钟的限制时,我被重定向到登录屏幕。
AFAIU,当普通令牌过期时,库应该使用刷新令牌,然后我将收到一个新的令牌和一个新的刷新令牌。因此,在5/40分钟方案中,每隔5分钟,我将收到一个新的令牌(使用刷新令牌获得)和一个新的刷新令牌,其过期时间为40分钟(从应用程序启动时间开始算起45分钟)。所以当40分钟到达时,我应该已经收到了8个新的令牌和刷新令牌,所以我的刷新令牌只有5分钟的时间,我应该得到一个新的令牌,没有问题。但实际情况是,它会使用接收到的第一个刷新令牌,并尝试每次都使用它。
我想这可能有点混乱。我来解释一下:
- 第一次登录在15:00。获得令牌AAA(15:05到期)和刷新令牌BBB(15:40到期)
- 15:05 =比;令牌AAA过期,在onTokenExpired事件中更新令牌。库使用令牌BBB来获取新的令牌。
- AFAIU,我收到令牌CCC(过期15:10)和新的刷新令牌DDD(过期15:45)
- = 15比;令牌CCC过期,在onTokenExpired事件中更新令牌。库使用令牌DDD来获取新的令牌。
- AFAIU,我收到令牌EEE(过期15:15)和新的刷新令牌FFF(过期15:50)
…以此类推直到
- 15:35 =比;token MMM过期,在onTokenExpired事件中更新token。该库使用令牌NNN来获取新的令牌。
- 我收到令牌oo(过期15:40)和一个新的刷新令牌PPP(过期16:15)
- 15:40 =比;令牌OOO过期,在onTokenExpired事件中更新令牌。库使用令牌PPP来获取新的令牌。
- AFAIU,我应该收到令牌QQQ(过期15:40)和一个新的刷新令牌RRR(过期16:15)
但是在这一刻,当我访问keycloak服务器URL时,我得到一个OnAuthLogout事件和一个400错误。这就像如果它一直使用刷新令牌AAA,尽管调试表明令牌和刷新令牌属性被正确更新。
我调试了token, refreshToken, tokenParsed和refreshTokenParsed,它们在每次正常的令牌刷新时都正确更新。
下面是调试的粘贴目录。我只更改了与公司相关的敏感数据和令牌中间的一些字符,以便使它们无效。请按首尾字符进行比较:
https://pastebin.com/FStZzpE2https://gist.github.com/nelson777/6066bb6631634da51510ba27b8ec064bhttps://ghostbin.com/paste/sOyxZ
(3个选项,因为Pastebin安全删除了原始帖子,认为我共享了敏感数据)
我做错了什么?下面是我的代码:
const initOptions: any =
{
adapter: 'default',
onLoad: 'login-required',
checkLoginIframe: false,
checkLoginIframeInterval: 86400,
enableLogging: true
};
let keycloackConfig = {
config: environment.keycloakConfig,
initOptions,
bearerExcludedUrls: [],
loadUserProfileAtStartUp: false
};
console.log('keycloackConfig', keycloackConfig);
let authenticated = await keycloak.init(keycloackConfig);
if (!authenticated)
return res(0);
let u2t = ut => {
let d = new Date(ut * 1000);
return `${('' + d.getHours()).padStart(2, '0')}:${('' + d.getMinutes()).padStart(2, '0')}:${('' + d.getSeconds()).padStart(2, '0')}`;
}
let keycloakInstance = keycloak.getKeycloakInstance();
console.log('keycloak', keycloak, keycloakInstance);
console.log('tokens', keycloakInstance.token, keycloakInstance.refreshToken);
console.log('tokenParsed', u2t(keycloakInstance.tokenParsed.iat), u2t(keycloakInstance.tokenParsed.exp));
console.log('refreshTokenParsed', u2t(keycloakInstance.refreshTokenParsed.iat), u2t(keycloakInstance.refreshTokenParsed.exp));
console.log(keycloak.keycloakEvents$);
from(keycloak.keycloakEvents$)
.subscribe((event: any) => {
if (event.type == KeycloakEventType.OnTokenExpired)
keycloakInstance.updateToken(30);
console.log('keycloak token event', event.type);
console.log('tokens', keycloakInstance.token, keycloakInstance.refreshToken);
console.log('tokenParsed', u2t(keycloakInstance.tokenParsed.iat), u2t(keycloakInstance.tokenParsed.exp));
console.log('refreshTokenParsed', u2t(keycloakInstance.refreshTokenParsed.iat), u2t(keycloakInstance.refreshTokenParsed.exp));
})
keycloak.getKeycloakInstance().loadUserInfo().success(async (user: KeycloakUsuario) => {
usuarioService.obterPorLoginComContasAdmin(user.username).subscribe(
<whatever>
就把它留在这里:我已经找到了解决方案。
问题不在于代币。它们正在被更新和正确使用。我的申请是一个视频和生活网站。当用户开始观看视频或直播时,它会在同一页面停留很长时间。因此,由于这种不活动,Keycloak认为会话"空闲"。并发送一个Logout事件。
解决方案是使用scope: offline_access
,因为这样keycloak将忽略"空闲时间"。配置。但scope
选项仅在login()
法中可用,在init()
法中不可用。
在initOptions中,你删除了这行
onLoad: 'login-required',
则在调用keycloak.init(keyclockConfig)
时不会自动进行身份验证。所以你必须手动设置scope选项:
await keycloak.init(keycloackConfig);
await keycloak.login({
scope: 'offline_access',
});
则不再考虑空闲时间配置。
您可以增加空闲时间。在"令牌"选项卡的"领域设置"中。所以你不需要做这些额外的步骤。