1

对于我正在使用这个库的项目:angular-oauth2-oidc支持 OAuth 2 和 Angular 中的 OpenId Connect (OIDC)。

我已经设置好了一切,一切正常。

主要组件文件:

export class MainComponent implements OnInit {

  constructor() {
    this.configureSSO();
  }

  configureSSO() {
    this.oAuthService.configure(authConfig);
    this.oAuthService.tokenValidationHandler = new JwksValidationHandler();

    this.oAuthService.loadDiscoveryDocumentAndTryLogin().then(() => {
      // the lib received the access_token as well as the id_token, if it was requested. 
      // If there is an id_token, the lib validated it.
      // DO STUFF WITH TOKEN HERE
    });
  }
}

授权配置文件:

import {AuthConfig} from 'angular-oauth2-oidc';

export const authConfig: AuthConfig = { /...SOME CONFIG HERE .../ }

AuthGuard 文件:

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private router: Router, private oAuthService: OAuthService) {
  }

  canActivate(): boolean {
    if(this.oAuthService.hasValidIdToken()){
      return true;
    }
    return false;
  }
}

在 OIDC Providers 站点上成功登录后,我可以看到 access_token 保存在本地浏览器的会话存储中:

在此处输入图像描述

这一切都很完美,但是,如果我现在继续更改会话存储中的令牌,我仍然能够进入我的受保护路线。虽然access_token 改了。改的时候id_token也是一样。

--> AuthGuard 仍然允许我访问受保护的路由。

有人能告诉我这怎么可能吗?

我无法在文档文档 angular-oauth2-oidc中找到有关内部处理方式的任何信息

我很确定这不是实现错误,而是库将令牌保存在内部某处,并改用未更改的令牌,因为其他一切都按预期完美运行。

但是,如果没有(真的)使用令牌,为什么还要将令牌保存在会话存储中?!?

更多的:

如果我真的从存储中删除了整个令牌,所有被阻止的路由实际上都被阻止了——这很好!当我将 JWT 中的到期时间 (exp) 更改为实际时间之前的某个值时,也会发生同样的事情。所以这两项检查实际上工作正常,但是当更改access_tokenid_tokenAuthGuard 仍然获得有效令牌时......(可能来自库内部?!?)

我认为总体上对 JWT 有一些我不理解的地方,以及为什么它们甚至保存在本地/会话存储中,或者为什么对它们的更改没有效果......

非常感谢任何答案。

4

1 回答 1

0

在基本场景中,库将假定 JavaScript 的每一点都与会话存储“配合得很好”,有效地将其视为库的私有存储。如果你想清除登录以便路由守卫可以取走它,你不应该自己撬开存储,而是调用logout服务。这将有效地清除存储

基本上,如果您从 sessionStorage(或 localStorage,如果您要使用它)中删除“属于”库的内容,那么您就是在破坏它。

你的守卫是一个应用程序关注点,他们应该能够信任库(反过来应该能够信任存储),以确定如果库认为用户“登录”会发生什么。

除非您告诉它,否则库本身通常根本不使用令牌。最常见的情况是提供模块配置以确保将 access_token 发送到您的 API。例如:

{ 
  provide: OAuthModuleConfig,
  useValue: {
    resourceServer: {
      allowedUrls: ['https://example.org/my-api'],
      sendAccessToken: true
    }
  }
}

现在,如果您想“保护”免受其他代码干扰库的存储,您可以provide自己实现OAuthStorage,例如:

function storageFactory() {
  const privateStore = {};

  return {
    getItem(key) { return privateStore[key]; }
    removeItem(key) { delete privateStore[key]; }
    setItem(key, data) { privateStore[key] = data; }
  };
}
{ provide: OAuthStorage, useFactory: storageFactory }

我使用类似的方法来提供localStorage而不是sessionStorage在我的示例存储库中提供。

于 2020-04-12T18:35:27.587 回答