Undvik sidbelastningar när du hämtar och förnyar token tyst med hjälp av MSAL.js

Microsoft-autentiseringsbibliotek för JavaScript (MSAL.js) använder dolda iframe element för att hämta och förnya token tyst i bakgrunden. Microsoft Entra ID returnerar token tillbaka till den registrerade redirect_uri som anges i tokenbegäran (som standard är det appens rotsida). Eftersom svaret är en 302 innebär det att HTML-koden som motsvarar redirect_uri läses in i iframe. Vanligtvis utgör appens redirect_uri rotsida, vilket gör att den laddas om.

I andra fall kan det, om navigering till appens rotsida kräver autentisering, leda till kapslade iframe-element eller X-Frame-Options: deny-fel.

Eftersom MSAL.js inte kan avvisa 302-omdirigeringen som utfärdas av Microsoft Entra ID och måste bearbeta den returnerade tokenen, kan det inte förhindra att redirect_uri läses in i iframe.

Följ dessa lösningar för att undvika att hela appen läses in igen eller andra fel som orsakas på grund av detta.

Ange olika HTML-kod för iframe

Ställ in egenskapen redirect_uri i konfigurationen till en enkel sida som inte kräver autentisering. Du måste se till att den matchar den redirect_uri som är registrerad i Microsoft Entra-administrationscenter. Detta påverkar inte användarens inloggning eftersom MSAL sparar startsidan när användaren påbörjar inloggningsprocessen och omdirigerar tillbaka till den exakta platsen när inloggningen har slutförts.

Initiering i huvudappfilen

Om din app är strukturerad så att det finns en central JavaScript-fil som definierar appens initiering, routning och annat kan du villkorligt läsa in dina appmoduler baserat på om appen läses in i en iframe eller inte. Ett exempel:

I 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
            );
        }]);
}

I 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) {
  }
}

Nästa steg

Läs mer om att skapa ett ensidesprogram (SPA) med hjälp av MSAL.js.