【问题标题】:Angular OAuth Code Flow Authentication with IDP(Keycloak)使用 IDP(Keycloak)的 Angular OAuth 代码流身份验证
【发布时间】:2022-07-07 04:11:32
【问题描述】:

我正在尝试与我的 Angular 项目中的身份提供程序(在我的情况下为 Keycloak)集成。为此,我正在使用“angular-oauth2-oidc”库。

因此,我可以通过单击按钮将用户从我的主页重定向到 IDP 的登录页面,并在成功登录后将我重定向回原来的页面。到目前为止一切顺利,但我的问题是在登录过程之后,包括令牌在内的会话信息未设置到我的浏览器的会话存储中。如果我重复这个过程(再次调用登录函数),它就会正确设置它们。

以下是我目前编写的代码;

auth.service.ts

  constructor(private oauthService: OAuthService) {}

  authConfig: AuthConfig = {
    issuer: environment.keycloak.issuerAddress,
    redirectUri: window.location.origin + '/home',
    clientId: environment.keycloak.clientId,
    scope: environment.keycloak.scope,
    responseType: environment.keycloak.responseType,
    disableAtHashCheck: environment.keycloak.disableAtHashCheck,
    showDebugInformation: environment.keycloak.showDebugInformation,
  }

  login(): Promise<any> {
    return new Promise<void>((resolveFn, rejectFn) => {
      this.initLogin().then(() => {
        resolveFn();
      }).catch(function(e){
        rejectFn(e);
      });
    });
  }

  private initLogin(): Promise<any> {
    return new Promise<void>((resolveFn, rejectFn) => {
      this.oauthService.configure(this.authConfig);
      this.oauthService.tokenValidationHandler = new JwksValidationHandler();
      this.oauthService.loadDiscoveryDocumentAndTryLogin().then(() => {
        if (this.oauthService.hasValidAccessToken()) {
          this.oauthService.setupAutomaticSilentRefresh();
          resolveFn();
        }else {
          this.oauthService.initCodeFlow();
          resolveFn();
        }
      }).catch(function(e){
        rejectFn("Identity Provider is not reachable!");
      });
    });
  }

home.component.ts

 login(): void {
    this.authService.login().then(() => {
      //
    }).catch((e) =>{
      //
    });
 }

总之,我想要做的是;

  • 当用户点击登录按钮时,配置oauthService并尝试登录。
  • 如果已有有效的访问令牌,则只需设置静默刷新并返回。
  • 如果没有有效的访问令牌,则启动代码流并重定向到 IDP 的登录页面。
  • 如果登录尝试因异常而失败,请告知用户 IDP 不可用。

注意: 如果我改为在构造函数中进行 oauthService 配置,并且仅在用户要登录时调用 oauthService.initCodeFlow() 方法,则它可以正常工作。我没有在构造函数中配置它的原因是我希望能够在用户单击登录按钮时告诉用户 IDP 不可用。

【问题讨论】:

    标签: angular keycloak idp angular-oauth2-oidc


    【解决方案1】:

    我觉得create a guard that enforces login 最干净。然后,您可以现在决定在您的所有路线上设置该守卫,但它也允许您稍后对此进行例外处理。例如,您的应用程序中的常见问题解答页面可能是公开的?在此处复制上述守卫的代码:

    canActivate(
        route: ActivatedRouteSnapshot,
        state: RouterStateSnapshot,
    ): Observable<boolean> {
        return this.authService.isDoneLoading$.pipe(
          filter(isDone => isDone),
          switchMap(_ => this.authService.isAuthenticated$),
          tap(isAuthenticated => isAuthenticated || this.authService.login(state.url)),
        );
    }
    

    它将等待授权逻辑为isDoneLoading$,以确保完成所有异步授权引导。然后它检查用户是否通过了身份验证,如果没有,则将用户发送出去登录,但将参数中的目标页面记住为login(...)。当用户返回您的应用程序时,url 将返回给您。

    在您的应用程序的登录序列(此处为my sample)中,您可以阅读此state 并使用它将用户发送到最初预期的页面。守卫现在应该允许这样做,因为用户已经登录了。

    以下是执行此操作的登录序列的相关部分:

        // Check for the strings 'undefined' and 'null' just to be sure. Our current
        // login(...) should never have this, but in case someone ever calls
        // initImplicitFlow(undefined | null) this could happen.
        if (this.oauthService.state && this.oauthService.state !== 'undefined' && this.oauthService.state !== 'null') {
          let stateUrl = this.oauthService.state;
          if (stateUrl.startsWith('/') === false) {
            stateUrl = decodeURIComponent(stateUrl);
          }
          console.log(`There was state of ${this.oauthService.state}, so we are sending you to: ${stateUrl}`);
          this.router.navigateByUrl(stateUrl);
        }
    

    【讨论】:

      猜你喜欢
      • 2020-05-22
      • 2021-09-08
      • 2020-12-28
      • 2019-01-28
      • 2012-01-20
      • 2017-05-09
      • 2020-05-28
      • 2020-03-03
      • 1970-01-01
      相关资源
      最近更新 更多