identityserver4 - 使用 Identity Server 4、VueJS 和 oidc-client 检查会话失败后自动注销
问题描述
我正在我的机器上测试服务器和客户端,我遇到以下情况:我很好地登录到客户端,做一些工作,关闭浏览器而不注销。然后我再次打开客户端,我仍然登录(预期)但一分钟后我自动注销(不预期)。
我正在使用这样配置的 oidc-client.js:
var mgr = new Oidc.UserManager({
userStore: new Oidc.WebStorageStateStore({ store: window.localStorage }),
authority: 'http://localhost:5000',
client_id: 'TST_PORTAL',
redirect_uri: window.location.origin + '/static/callback.html',
response_type: 'code id_token token',
scope: 'api47 openid profile read write offline_access active_dir email',
post_logout_redirect_uri: window.location.origin + '/',
silent_redirect_uri: window.location.origin + '/static/silent-renew.html',
accessTokenExpiringNotificationTime: 10,
automaticSilentRenew: true,
filterProtocolClaims: true,
loadUserInfo: true
})
经过进一步调查,我看到客户端正在调用 /connect/checksession(返回状态 200)以支持单点注销,然后调用 /connect/authorize?client_id... 失败(302 重定向到 /home/error)。身份服务器日志显示“授权请求中没有用户”和“客户端的无效授权类型:隐式。我配置了混合和 client_credentials。我在这里阅读了一些内容,所以我将此代码添加到我的 IdentityServer 启动中:
services.ConfigureApplicationCookie(options =>
{
options.Cookie.SameSite = SameSiteMode.None;
});
但这似乎没有帮助。
大声思考,这可能是一个跨域问题,因为它们在不同的端口上运行,或者我没有正确设置 COR?我没有看到 cors 错误。checksession GET请求也应该有参数吗?我一直在阅读规范,它讨论的是 iframe,而不是网络流量,所以我不确定这个流量应该是什么样子。
更新:
我的应用程序的第一页是一个匿名身份验证登录页面,用于检查他们是否已登录。如果是,它将他们重定向到主页。检查的代码是这样的:
// Get signed in status without prompting to log in
getIsSignedIn() {
console.log('Checking if signed in');
return new Promise((resolve, reject) => {
mgr.getUser().then(function (user) {
if (user == null) {
console.log('Not Signed In');
return resolve(false)
} else {
if (user.expired) {
console.log('User expired');
return resolve(false)
} else {
console.log('Signed In');
return resolve(true)
}
}
}).catch(function (err) {
console.log('Error when checking if signed in');
return reject(false)
});
})
}
即使我打开一个新的浏览器,这似乎也恢复了。我什至将 Oidc.WebStorageStateStore 更改为使用默认值而不是 localStorage。
解决方案
有很多事情可能会导致这种行为。
1)单点注销(monitorSession:true)这是做什么的?-- 登录到您的应用程序后(从 IDP 服务器发布重定向后,OIDC-Client JS 将在 iframe 中包含 CheckSession 端点,并且 OIDC 库每 2 秒(默认)在内部 ping 此 iframe 以验证 idsrv.session cookie 值是否匹配使用应用程序 id 令牌中的值,如果它们不匹配,OIDC 将引发用户退出事件addUserSignedOut
。这取决于您的应用程序,当这甚至从 OIDC 引发时,您希望如何处理。仅仅因为您启用了单点注销,除非应用程序处理,否则不会将用户带回登录页面。
2) Silent-Renew (automaticSilentRenew: true) 当您将此标志启用为 true 时,您无法控制何时应该进行静默更新,默认情况下,它发生在访问令牌过期时间的 1 分钟之前。所以如果silentrenew 失败,会引发silentrenew 事件addSilentRenewError
。这取决于您的应用程序,当这甚至从 OIDC 提出时,您希望如何处理。
3)如果您关闭整个浏览器并转到 url 应用程序 URL,则应删除身份服务器 cookie,因为它们是会话 cookie。因此,如果您处理了单点注销事件,那么 OIDC 将在应用程序加载后的 2 秒内引发注销事件。由于您没有看到登录页面,我假设您可能没有在应用程序中处理此事件。
4)当静默更新发生时(在令牌到期时间 1 分钟之前),这一次您的应用程序将与 IDP 服务器通信,但是当您关闭浏览器时您将没有会话 cookie,您将收到静默更新错误(可能这次,您可能已经看到了您描述的错误)并且在这种情况下您必须处理silentrenew 错误,这就是您看到登录屏幕的原因。(只是基于您的输入的疯狂假设)。
希望这可以帮助 !!
推荐阅读
- python - 我的电报机器人在个人聊天中回答,但不在群聊中。为什么?
- html - 使网格页面的整个部分具有不同的背景颜色
- sql - 基于开始和结束日期的 Oracle SQL 数据迁移
- java - notifyDataSetChanged 在 kotlin 的适配器中不起作用
- java - 运行时的 GUI 与 NetBeans GUI 构建器上的设计 GUI 不同
- jdbc - JDBC 属性 - 全有或全无
- python - RuntimeError:事件循环已关闭“Launcher.killChrome”从未等待,如何解决?
- javascript - 使用一个正则表达式的字符串后面的项目的多次匹配
- javascript - 在 React 中执行时如何禁用点击事件?
- javascript - 汽车贷款计算器公式