首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >离子认证和MSAL认证

离子认证和MSAL认证
EN

Stack Overflow用户
提问于 2021-09-30 11:20:20
回答 3查看 3K关注 0票数 5

我有一个Ionic应用程序需要在Azure中进行身份验证,所以我按照本教程安装了MSAL:https://learn.microsoft.com/en-us/graph/tutorials/angular

它的工作原理就像“离子服务”的魅力,但当我在设备中运行它时,当我试图登录Azure时,它就会崩溃。我认为这是因为在Ionic中不允许弹出窗口MSAL显示登录。

因此,我的第一次尝试是更改loginPopup()对loginRedirect()的调用。所以我删除了这个代码:

代码语言:javascript
复制
async signIn(): Promise<void> {
  const result = await this.msalService
    .loginPopup(OAuthSettings)
    .toPromise()
    .catch((reason) => {
      this.alertsService.addError('Login failed',
        JSON.stringify(reason, null, 2));
    });

  if (result) {
    this.msalService.instance.setActiveAccount(result.account);
    this.authenticated = true;
    this.user = await this.getUser();
  }
}

我添加了这个新的(基于https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/errors.md):

代码语言:javascript
复制
async signIn(): Promise<void> {
  await this.msalService.instance.handleRedirectPromise();

  const accounts = this.msalService.instance.getAllAccounts();
  if (accounts.length === 0) {
    // No user signed in
    this.msalService.instance.loginRedirect();
  }
}

但是这样,用户信息就不会被保存,因为我没有要处理或调用setActiveAccount(结果)的“结果”。它甚至在“离子服务”中也不起作用,所以我放弃了这种方法。

第二种方法是在搜索一个可实现的解决方案两天后,在InAppBrowser (https://ionicframework.com/docs/native/in-app-browser)中显示弹出窗口,因此我将代码更改为:

代码语言:javascript
复制
async signIn(): Promise<void> {
  const browser = this.iab.create('https://www.microsoft.com/');
  browser.executeScript({ code: "\
    const result = await this.msalService\
      .loginPopup(OAuthSettings)\
      .toPromise()\
      .catch((reason) => {\
        this.alertsService.addError('Login failed',\
          JSON.stringify(reason, null, 2));\
      });\
    if (result) {\
      this.msalService.instance.setActiveAccount(result.account);\
      this.authenticated = true;\
      this.user = await this.getUser();\
    }"
  }); 
}

但是它只是打开一个新窗口,没有做更多的事情,它不执行loginPopup(),所以我也放弃了第二个方法。

有人知道如何避免在Ionic中出现弹出问题吗?

谢谢

EN

回答 3

Stack Overflow用户

发布于 2021-12-13 16:08:44

通过使用自定义导航客户端,我设法用cordova-plugin解决了这个问题,下面是我的实现:

CustomNavigationClient

代码语言:javascript
复制
    class CustomNavigationClient extends NavigationClient {
      async navigateExternal(url: string, options: any) {
        // Cortdova implementation
        if (window.hasOwnProperty("cordova")) {
          var ref = cordova.InAppBrowser.open(url, '_blank', 'location=yes,clearcache=yes,clearsessioncache=yes');

          // Check if the appbrowser started a navigation
          ref.addEventListener('loadstart', (event: any) => {
            // Check if the url contains the #state login parameter
            if (event.url.includes('#state')) {
              // Close the in app browser and redirect to localhost + the state parameter
              // msal-login is a fake route to trigger a page refresh
              ref.close();
              const domain = event.url.split('#')[0];
              const url = event.url.replace(domain, 'http://localhost/msal-login');
              window.location.href = url;
            }
          });
        } else {
          if (options.noHistory) {
            window.location.replace(url);
          } else {
            window.location.assign(url);
          }
        }
        return true;
      }
    }

app.component.ts

代码语言:javascript
复制
    const navigationClient = new CustomNavigationClient();
    this.msalService.instance.setNavigationClient(navigationClient);
    
    this.msalService.instance.handleRedirectPromise().then((authResult: any) => {
      console.debug('AuthResult ---->', authResult);
      if (authResult) { 
        // your login logic goes here. 
      } else {
        this.msalService.instance.loginRedirect();
      }
    });
票数 4
EN

Stack Overflow用户

发布于 2022-02-12 23:49:21

我可以确认Paolo Cuscelas的解决方案是有效的。我们使用的是离子电容器和cordova InAppBrowser,因为电容器浏览器不支持监听url更改,这是为了“代理”msal路由参数而需要的。

另外,请确保在您的蔚蓝门户中注册重定向uri。

应用程序的其余部分或多或少是基于microsoft提供的msal/角包示例设置的。

电容器CustomNavigationClient

确保将msal交互类型设置为"InteractionType.Redirect“

构造函数要求传入一个InAppBrowser引用。

另外,azure通过#代码而不是#state返回url中的数据,因此请确保相应地拆分url。

代码语言:javascript
复制
class CustomNavigationClient extends NavigationClient {

  constructor(private iab: InAppBrowser) {
    super();
  }

  async navigateExternal(url: string, options: any) {
    if (Capacitor.isNativePlatform()) {
      const browser = this.iab.create(url, '_blank', {
        location: 'yes',
        clearcache: 'yes',
        clearsessioncache: 'yes',
        hidenavigationbuttons: 'yes',
        hideurlbar: 'yes',
        fullscreen: 'yes'
      });
      browser.on('loadstart').subscribe(event => {
        if (event.url.includes('#code')) {
          // Close the in app browser and redirect to localhost + the state parameter
          browser.close();
          
          const domain = event.url.split('#')[0];
          const url = event.url.replace(domain, 'http://localhost/home');
          console.log('will redirect to:', url);
          window.location.href = url;
        }
      });
    } else {
      if (options.noHistory) {
        window.location.replace(url);
      } else {
        window.location.assign(url);
      }
    }
    return true;
  }
}

app.component.ts

注册导航客户端

代码语言:javascript
复制
import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { InAppBrowser } from '@awesome-cordova-plugins/in-app-browser/ngx';
import { MsalBroadcastService, MsalService } from '@azure/msal-angular';
import { AuthenticationResult, EventMessage, EventType, NavigationClient } from '@azure/msal-browser';
import { Capacitor } from '@capacitor/core';
import { Subject } from 'rxjs';
import { filter, tap } from 'rxjs/operators';
import { AzureAuthService } from '@core/auth';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {

  constructor(
    private azureAuthService: AzureAuthService,
    private authService: MsalService,
    private msalBroadcastService: MsalBroadcastService,
    private router: Router,
    private iab: InAppBrowser,
    private msalService: MsalService,
  ) {
    this.msalService.instance.setNavigationClient(new CustomNavigationClient(this.iab));
  }

  ngOnInit(): void {

    this.msalBroadcastService.msalSubject$
      .pipe(
        filter((msg: EventMessage) => msg.eventType === EventType.LOGIN_SUCCESS),
      )
      .subscribe((result: EventMessage) => {
        console.log('--> login success 1: ', result);
        const payload = result.payload as AuthenticationResult;
        this.authService.instance.setActiveAccount(payload.account);

        // custom service to handle authentication result within application
        this.azureAuthService.handleAuthentication(payload) 
          .pipe(
            tap(() => {
              console.log('--> login success 2: ');
              this.router.navigate(['/home']);
            })
          )
          .subscribe();
      });
  }

}

package.json

如果使用angulars方法,请确保将依赖项放置在项目特定的package.json文件中,否则,当同步插件(cordova和电容器)与npx上限同步时,插件将被忽略。会导致"...plugin_not_installed“错误。

代码语言:javascript
复制
"dependencies": {
    ...
    "@capacitor/android": "3.4.1",
    "cordova-plugin-inappbrowser": "^5.0.0",
    "@awesome-cordova-plugins/in-app-browser": "^5.39.1",
    "@azure/msal-angular": "^2.0.1",
    "@azure/msal-browser": "^2.15.0",
    ...
}
票数 3
EN

Stack Overflow用户

发布于 2022-09-15 10:45:43

我确认Jazjef解决方案可以在Ionic 6上使用电容解决安卓工作白白问题,但IOS需要更改event.url.replace代码以使用电容://localhost/重定向到应用程序,如果让'http://localhost/‘在系统浏览器上打开url,

代码语言:javascript
复制
async navigateExternal(url: string, options: any) {
// Cortdova implementation
if (Capacitor.isNativePlatform()) {
  var browser = this.iab.create(url, '_blank', 'location=yes,clearcache=yes,clearsessioncache=yes,hidenavigationbuttons=true,hideurlbar=true,fullscreen=true');

  browser.on('loadstart').subscribe(event => {
     if (event.url.includes('#code')) {
       browser.close();
      const domain = event.url.split('#')[0];
     const url = event.url.replace(domain, 'capacitor://localhost/home');
      window.location.href = url;
    }


  });


} else {
  if (options.noHistory) {
   // window.location.replace(url);
  } else {
   // window.location.assign(url);
  }
}
return true;

}

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69391322

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档