次の方法で共有


MSAL.js を使用してトークンを自動的に取得、更新するときにページのリロードを回避する

JavaScript (MSAL.js) 用 Microsoft Authentication Library では非表示の iframe 要素を使用して、バックグラウンドでトークンが自動的に取得、更新されます。 Microsoft Entra ID によって、トークン要求で指定された登録済み redirect_uri にトークンが戻されます (既定では、これはアプリのルート ページです)。 応答は 302 なので、結果は redirect_uri にロードされる iframe に対応する HTML になります。 通常、アプリの redirect_uri はルート ページで、これにより、リロードされます。

他のケースでは、アプリのルートページへの移動に認証が必要な場合、入れ子状のiframe要素やX-Frame-Options: denyエラーが発生することがあります。

MSAL.js は Microsoft Entra ID によって発行された 302 を無視できず、返されたトークンを処理する必要があるため、 redirect_uriiframeに読み込まれないようにすることはできません。

アプリ全体のリロードやこれにより発生するその他のエラーを回避するには、次の回避策に従ってください。

iframe に別の HTML を指定する

config の redirect_uri プロパティを、認証を必要としない単純なページに設定します。 Microsoft Entra 管理センターに登録されている redirect_uri と一致していることを確認する必要があります。 ユーザーがログイン プロセスを開始し、ログインが完了した後に正確な場所にリダイレクトされるときに、MSAL によってスタート ページが保存されるため、これはユーザーのログイン エクスペリエンスには影響しません。

メインのアプリケーションファイルで初期化を行う

アプリの初期化、ルーティングなどを定義する中央の単一 JavaScript ファイルが存在するようにアプリが構成されている場合、アプリが iframe に読み込まれるかどうかに基づいてアプリ モジュールを条件付きで読み込むことができます。 例えば次が挙げられます。

AngularJS: app.js の場合

// Check that the window is an iframe and not popup
if (window !== window.parent && !window.opener) {
angular.module('todoApp', ['ui.router', 'MsalAngular'])
    .config(['$httpProvider', 'msalAuthenticationServiceProvider','$locationProvider', function ($httpProvider, msalProvider,$locationProvider) {
        msalProvider.init(
            // msal configuration
        );

        $locationProvider.html5Mode(false).hashPrefix('');
    }]);
}
else {
    angular.module('todoApp', ['ui.router', 'MsalAngular'])
        .config(['$stateProvider', '$httpProvider', 'msalAuthenticationServiceProvider', '$locationProvider', function ($stateProvider, $httpProvider, msalProvider, $locationProvider) {
            $stateProvider.state("Home", {
                url: '/Home',
                controller: "homeCtrl",
                templateUrl: "/App/Views/Home.html",
            }).state("TodoList", {
                url: '/TodoList',
                controller: "todoListCtrl",
                templateUrl: "/App/Views/TodoList.html",
                requireLogin: true
            })

            $locationProvider.html5Mode(false).hashPrefix('');

            msalProvider.init(
                // msal configuration
            );
        }]);
}

Angular で: app.module.ts

// Imports...
@NgModule({
  declarations: [
    AppComponent,
    MsalComponent,
    MainMenuComponent,
    AccountMenuComponent,
    OsNavComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),
    MsalModule.forRoot(environment.MsalConfig),
    SuiModule,
    PagesModule
  ],
  providers: [
    HttpServiceHelper,
    {provide: HTTP_INTERCEPTORS, useClass: MsalInterceptor, multi: true},
    AuthService
  ],
  entryComponents: [
    AppComponent,
    MsalComponent
  ]
})
export class AppModule {
  constructor() {
    console.log('APP Module Constructor!');
  }

  ngDoBootstrap(ref: ApplicationRef) {
    if (window !== window.parent && !window.opener)
    {
      console.log("Bootstrap: MSAL");
      ref.bootstrap(MsalComponent);
    }
    else
    {
    //this.router.resetConfig(RouterModule);
      console.log("Bootstrap: App");
      ref.bootstrap(AppComponent);
    }
  }
}

MsalComponent です。

import { Component} from '@angular/core';
import { MsalService } from '@azure/msal-angular';

// This component is used only to avoid Angular reload
// when doing acquireTokenSilent()

@Component({
  selector: 'app-root',
  template: '',
})
export class MsalComponent {
  constructor(private Msal: MsalService) {
  }
}

次のステップ

複数パートのチュートリアル シリーズで、ユーザーをサインインさせる React シングルページ アプリケーション (SPA) を構築して、さらに詳しく学習します。