Angular MSAL (v2) 通过重定向登录,在获取令牌之前重定向 3 次或更多次

Ven*_*tor 6 azure-ad-msal angular msal-angular

我有一个 Angular 应用程序 ( v11.2.0 ),它使用 MSAL 进行身份验证。我最近升级到该库的 v2(@azure/msal-angular - ^2.1.1、@azure/msal-browser - ^2.22.0),并且由于 MSAL 更改而进行了一些重构。除了对用户进行身份验证并获取身份验证响应时之外,它的大部分工作方式与以前一样:该过程在成功获取身份验证响应之前循环大约 3 次,每次都会明显刷新应用程序。我看到的大致流程如下:

  • 循环1
  • 导航至应用程序
  • 用户未经过身份验证
  • 处理重定向启动
  • 处理重定向承诺调用但没有正在进行的交互,返回 null
  • 处理重定向结束
  • 登录开始
  • 收到空认证结果
  • 循环2
  • 导航至应用程序
  • 用户未经过身份验证
  • 处理重定向启动
  • 循环3
  • 导航至应用程序
  • 用户未经过身份验证
  • 处理重定向启动
  • 信息 - 获取令牌调用中
  • 登录成功
  • 处理重定向结束
  • 获取令牌启动
  • 收到认证结果

身份验证在我的 app.component.ts 中启动和处理:

ngOnInit() {
   this.msalBroadcastService.inProgress$
      .pipe(
         filter((status: InteractionStatus) => status === InteractionStatus.None)
      )
      .subscribe(async () => {
         if (!this.authenticated) {
            await this.logIn();
         }
      })

   this.msalService.handleRedirectObservable().subscribe({
      next: (result: AuthenticationResult) => {
         if (!this.msalService.instance.getActiveAccount() &&             
            this.msalService.instance.getAllAccounts().length > 0) {
               this.msalService.instance.setActiveAccount(result.account);
            }
         },
      error: (error) => console.log(error)
   });
}

async logIn() {
   await this.msalService.instance.loginRedirect({
      scopes: ['user.read', 'openid', 'profile'],
      redirectUri: AppConfig.settings.authenticationconfig.redirectUri
   });
};

get authenticated(): boolean {
   return this.msalService.instance.getActiveAccount() ? true : false;
}
Run Code Online (Sandbox Code Playgroud)

有没有人经历过类似的情况或了解导致这种行为的原因以及如何解决它?

Ven*_*tor 5

对我来说,最终的解决方案分为三个部分。

\n

第一个难题是遵循 @\xce\x95 \xd0\x93 \xd0\x98 \xd0\x86 \xd0\x98 \xd0\x9e 的答案,在 AppComponent 的 ngOnInit() 方法中进行以下更改 -

\n

前:

\n
// in app.component.ts        \nthis.msalService.handleRedirectObservable().subscribe({ \n   next: (result: AuthenticationResult) => {\n      if (!this.msalService.instance.getActiveAccount() && this.msalService.instance.getAllAccounts().length > 0) {\n         this.msalService.instance.setActiveAccount(result.account);\n      }\n   },\n   error: (error) => console.log(error)\n});\n
Run Code Online (Sandbox Code Playgroud)\n

后:

\n
// in app.component.ts       \nthis.msalBroadcastService.msalSubject$\n   .pipe(\n      filter(\n         (msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS \n         || msg.eventType === EventType.SSO_SILENT_SUCCESS)\n       ).subscribe((result: EventMessage) => {\n          const payload = result.payload as AuthenticationResult;\n          this.msalService.instance.setActiveAccount(payload.account);\n    });\n
Run Code Online (Sandbox Code Playgroud)\n

这停止了​​循环行为,但使应用程序处于挂起状态,并出现 interaction_in_progress BrowserAuthError。经过进一步挖掘,第二部分如下 -

\n

前:

\n
// in app.module.ts\nbootstrap: [AppComponent],\n
Run Code Online (Sandbox Code Playgroud)\n

&

\n
// in index.html\n<body>\n   <app-root></app-root>\n</body>\n
Run Code Online (Sandbox Code Playgroud)\n

后:

\n
// in app.module.ts\nbootstrap: [AppComponent, MsalRedirectComponent],\n
Run Code Online (Sandbox Code Playgroud)\n

&

\n
// in index.html\n<body>\n     <app-root></app-root>\n     <app-redirect></app-redirect>\n</body>\n
Run Code Online (Sandbox Code Playgroud)\n

我之前曾尝试过此操作,但收效甚微,但据推测,第一个代码更改与第二个代码更改结合使用。我所做的最后一个改变是——之前:

\n
// in app.component.ts \nthis.msalBroadcastService.inProgress$\n   .pipe(\n      filter((status: InteractionStatus) => status === InteractionStatus.None)\n   )\n   .subscribe(async () => {\n     if (!this.authenticated) {\n       await this.logIn();\n     }\n   });\n
Run Code Online (Sandbox Code Playgroud)\n

后:

\n
// in app.component.ts\nthis.msalBroadcastService.inProgress$\n   .pipe(filter((status: InteractionStatus) => status === InteractionStatus.None)\n   ,takeUntil(this._destroying$))\n   .subscribe(async () => {\n     if (!this.authenticated) {\n       await this.logIn();\n     }\n   });\n
Run Code Online (Sandbox Code Playgroud)\n

现在,应用程序的行为符合预期,从 Microsoft 登录页面重定向并立即加载应用程序 - 不再循环重新加载!

\n


Ε Г*_*И О 1

MSAL 因此类问题而臭名昭著。几乎没有人第一次就能做对。我不能确切地说你的代码有什么问题,但我会分享我使用的内容。也许它会给你一些指示。

msalService.handleRedirectObservable()我不是msalBroadcastService.msalSubject$这样,而是听着;

this.msalBroadcastService.msalSubject$
  .pipe(filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS || msg.eventType === EventType.SSO_SILENT_SUCCESS))
  .subscribe((result: EventMessage) => {
    const payload = result.payload as AuthenticationResult;
    this.msalService.instance.setActiveAccount(payload.account);
  });
Run Code Online (Sandbox Code Playgroud)