让angular-oauth2-oidc从其他选项卡中检索访问令牌

时间:2018-05-16 11:54:58

标签: angular typescript identityserver4 angular-oauth2-oidc

我将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(并立即返回到我的应用程序)。

我的问题:我可以让图书馆从同一来源的其他标签中检索现有的访问令牌(以及可选的用户信息),以防止重定向吗?(首选,因为它没有&#39;需要Ajax调用。)

或者,在我们将某人发送到IdentityServer之前,是否有一种简单的方法可以尝试使用静默刷新机制?

2 个答案:

答案 0 :(得分:3)

首先:我以某种方式认为sessionStorage适用于令牌,localStorage应该避免。但那是来自另一个涉及刷新令牌的项目,而且通过隐式流程我只有短暂的访问令牌,所以它不是那么大的问题。

我没有提到我有这个想法,the other answer帮助我重新思考并考虑使用localStorage。这实际上是一个很好的解决方案。

事实证明,该库已内置支持使用localStorage作为令牌和其他数据的后备存储。起初虽然我在尝试:

// This doesn't work properly though, read on...
this.oAuthService.setStorage(localStorage);

但是这种引导方式对我的情况并不起作用,请参阅issue 321 on the libraries GitHub issues list了解我的登录信息。从该线程重复解决方案(或解决方法?),我通过在app模块providers中执行此操作解决了问题:

{ provide: OAuthStorage, useValue: localStorage },

现在该库将正确使用localStorage,新标签(甚至是新窗口)将自动选择它。

作为脚注,如果您出于安全原因不想使用localStorage,只要它实现了OAuthStorage接口,您也可以提供自己的存储。然后,您自己的实现可以使用任何可用的选项卡间通信技术来“问”&#34;来自其他标签的数据,如果需要,可以回退到sessionStorage。

答案 1 :(得分:1)

有一个解释,为什么总是去IdentityServer澄清当前用户,这是你展示的代码。

每次打开标签页时,您的应用程序都会启动,并执行上面的代码。现在 - 所有这些支持SPA'a和Implicit流程的oidc库都将用户数据(access_token ...)存储在浏览器会话存储中。通过打开新选项卡,您将拥有一个新会话。

我的观点是 - 在尝试对Identity Server进行身份验证之前,您需要做一些事情。我指的是将所有用户信息从Session storage移动到Local storage。然后,位于同一应用程序(分别为同一源)下的选项卡将具有共享Local storage

所以你在应用程序开始的流程应该是这样的:

  1. 检查本地存储空间以获取用户信息
  2. 如果存在,请设置身份验证服务(包括静默刷新),但不要尝试登录。并将数据移动到会话存储(不确定这是否需要,但我想库会在那里查找)
  3. 如果不是 - 登录,然后将数据从会话存储移动到本地存储
  4. 当然,在静默续订回调中,您必须更新本地存储中的值(它们应该由会话中的库更新)。
  5. 最后,但并非最不重要 - 在退出时,你将不得不清理。
  6. 对我来说,这似乎是一个解决方案。现在 - 由你来决定是否值得花费。

    PS:只是为了澄清 - 我还没试过。我不能保证它会起作用,但是按照事件的顺序,它应该。