我正在将angular-oauth2-oidc库与Implicit Flow(使用IdentityServer4服务器)结合使用 . 我已成功设置the Silent Refresh suggestion from the docs .
以下是我在包装器服务中引导的方法:
private userSubject = new Subject<User>();
constructor(private config: ConfigService, private oAuthService: OAuthService)
{ }
// Called on app load:
configure(): void {
const config: AuthConfig = {
issuer: this.config.getIdentityUrl(),
logoutUrl: this.config.getIdentityUrl() + '/connect/endsession',
redirectUri: window.location.origin + '/',
silentRefreshRedirectUri: window.location.origin + '/silent-refresh.html',
clientId: 'my_client_id',
scope: 'openid profile my_api',
sessionChecksEnabled: true,
};
this.oAuthService.configure(config);
this.oAuthService.tokenValidationHandler = new JwksValidationHandler();
this.oAuthService
.loadDiscoveryDocumentAndLogin()
.then((_) => this.loadUserProfile());
this.oAuthService.setupAutomaticSilentRefresh();
}
private loadUserProfile() {
this.oAuthService.loadUserProfile()
.then((userProfile) => {
const user = new User(userProfile['name']);
this.userSubject.next(user);
});
}
但是,如果我在新选项卡中打开应用程序,用户也会被重定向到IdentityServer(并立即返回到我的应用程序) .
我的问题: can I get the library to retrieve existing access token (and optionally user info) from other tabs of the same origin, to prevent the redirects? (首选,因为它不需要Ajax调用 . )
或者,在我们将某人发送到IdentityServer之前,是否有一种简单的方法可以尝试使用静默刷新机制?
2 回答
有一个解释,为什么它总是去IdentityServer澄清当前用户,它是你已经显示的代码 .
每次打开选项卡时,都会启动您的应用程序,并执行上面的代码 . 现在 - 所有这些支持SPA'a和
Implicit
流的oidc库都将用户数据(access_token
...)存储在浏览器会话存储中 . 通过打开新选项卡,您将拥有一个新会话 .我的观点是 - 在尝试对Identity Server进行身份验证之前,您需要做一些事情 . 我指的是将所有用户信息从
Session storage
移动到Local storage
. 然后,在同一应用程序(分别是相同的源)下的选项卡将具有共享Local storage
.所以你在应用程序中的流程开始,应该是这样的:
检查本地存储以获取用户信息
如果存在,请设置身份验证服务(包括静默刷新),但不要尝试登录 . 并将数据移动到会话存储(不确定这是否需要,但我想库会在那里查找)
如果不是 - 登录,然后将数据从会话存储移动到本地存储
当然,在静默续订回调中,您必须更新本地存储中的值(它们应该由会话中的库更新) .
最后,但并非最不重要 - 在注销时,你将不得不清理 .
对我来说,这似乎是一个解决方案 . 现在 - 由您来决定是否值得花费 .
PS:只是为了澄清 - 我还没试过 . 我不能保证它会起作用,但是按照事件的顺序,它应该 .
首先:我不知何故认为
sessionStorage
对于令牌是正确的,应该避免localStorage
. 但这是来自另一个涉及刷新令牌的项目,并且在隐式流程中我只有短暂的访问令牌,所以这不是一个问题 .我没有提到我有这个想法,并且the other answer帮助我重新考虑事情并考虑使用localStorage . 这实际上是一个很好的解决方案 .
事实证明,该库已经内置支持使用
localStorage
作为令牌和其他数据的后备存储 . 起初虽然我在尝试:但是这种引导方式对我的情况不起作用,请参阅issue 321 on the libraries GitHub issues list以获取我的登录信息 . 从该线程重复解决方案(或解决方法?),我通过在app模块的_2792196中执行此操作来解决问题:
现在,库将正确使用localStorage,新的选项卡(甚至是新窗口)将自动获取它 .
作为脚注,如果您出于安全原因不想使用
localStorage
,只要它实现OAuthStorage
接口,您也可以提供自己的存储 . 然后,您自己的实现可以使用任何可用的选项卡间通信技术来从其他选项卡中获取数据,如果需要,可以回退到sessionStorage .