Einrichten der Seite "Umleitungsbrücke" im MSAL-Browser

Dieses Handbuch enthält frameworkspezifische Anweisungen zum Einrichten der Umleitungsbrückenseite, die in MSAL Browser v5 eingeführt wurde. Hintergrundinformationen dazu, warum die Umleitungsbrücke benötigt wird, finden Sie im v4 zu v5-Migrationshandbuch.

Warning

Die Redirect-Bridge-Seite darf NICHT mit Cross-Origin-Opener-Policy Headern ausgeliefert werden. Die Brückenseite ist ein Vermittler, der die Authentifizierungsantwort empfängt, nachdem der IdP den OAuth-Fluss abgeschlossen hat. Wenn auf der Brückenseite COOP-Header gesetzt sind, führt der Browser einen Wechsel der Browsing-Context-Gruppe durch, der den Kommunikationskanal zur Hauptanwendung trennt und damit genau das Problem wieder auftreten lässt, das die Brücke lösen soll.

Important

Nachdem Sie Ihre redirectUri so aktualisiert haben, dass sie auf die neue Redirect-Bridge-Seite verweist, MÜSSEN Sie auch die Redirect-URI in Ihrer Entra ID-App-Registrierung aktualisieren. Der URI muss exakt übereinstimmen – einschließlich Pfad, Protokoll und Port. Wenn die App-Registrierung nicht aktualisiert wird, führt dies zu redirect_uri_mismatch Fehlern.

Angular

  1. Erstellen Sie die Umleitungsbrückenkomponente (src/app/redirect/redirect.component.ts):
import { Component, OnInit } from "@angular/core";
import { broadcastResponseToMainFrame } from "@azure/msal-browser/redirect-bridge";

@Component({
    selector: "app-redirect",
    standalone: true,
    template: "<p>Processing authentication...</p>",
})
export class RedirectComponent implements OnInit {
    ngOnInit(): void {
        broadcastResponseToMainFrame().catch((error: Error) => {
            console.error("Error broadcasting response to main frame:", error);
        });
    }
}
  1. Fügen Sie die /redirect Route in Ihrer Routingkonfiguration hinzu. Die Umleitungsroute muss sich außerhalb von MsalGuard befinden, und die Umleitungsseite sollte keine API-Aufrufe ausführen, die MsalInterceptor auslösen würden (oder auf andere Weise MSAL-APIs aufrufen):
import { RedirectComponent } from "./redirect/redirect.component";

const routes: Routes = [
    { path: "redirect", component: RedirectComponent },
    // ... your other routes
];
  1. Stellen Sie sicher, dass der Build die Komponente enthält. Bei Verwendung einer Angular-Route-Komponente ist keine angular.json Ressourcenänderung erforderlich – die Angular CLI bündelt die Komponente automatisch. Wenn Sie eine statische redirect.html anstelle einer routingierten Komponente bevorzugen, fügen Sie sie dem Ressourcenarray hinzu:
// angular.json
{
    "projects": {
        "your-app": {
            "architect": {
                "build": {
                    "options": {
                        "assets": [
                            { "glob": "**/*", "input": "public" },
                            "src/redirect.html" // ← Add redirect bridge page
                        ]
                    }
                }
            }
        }
    }
}

Beispiel: Sehen Sie sich angular-standalone-sample und angular-modules-sample an.

Vite

Vite erfordert eine Multi-Page-Konfiguration, damit redirect.html als separater Einstiegspunkt in die Build-Ausgabe aufgenommen wird.

  1. Erstellen Sie redirect.html im Projektstammverzeichnis (neben index.html):
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Redirect</title>
</head>
<body>
    <p>Processing authentication...</p>
    <script type="module">
        import { broadcastResponseToMainFrame } from "@azure/msal-browser/redirect-bridge";

        broadcastResponseToMainFrame().catch((error) => {
            console.error("Error broadcasting response:", error);
        });
    </script>
</body>
</html>
  1. Aktualisieren vite.config.ts, um die Weiterleitungsseite als zweiten Eintrag hinzuzufügen:
import { defineConfig } from "vite";
import { resolve } from "path";

export default defineConfig({
    build: {
        rollupOptions: {
            input: {
                main: resolve(__dirname, "index.html"),
                redirect: resolve(__dirname, "redirect.html"), // ← Redirect bridge entry
            },
        },
    },
});

Während der Entwicklung (vite dev) wird die Umleitungsseite automatisch unter /redirect.html bereitgestellt. In Produktions-Builds erzeugt Rollup sowohl index.html als auch redirect.html im Ausgabeverzeichnis.

Beispiel: Sehen Sie sich das React-Router-Beispiel, typescript-sample und b2c-Sample an.

Webpack

Webpack erfordert einen dedizierten Einstiegspunkt und eine HtmlWebpackPlugin Instanz für die Umleitungsseite.

  1. Erstellen src/redirect.html:
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Redirect</title>
</head>
<body>
    <p>Processing authentication...</p>
    <!-- The redirect script bundle will be injected by HtmlWebpackPlugin (see redirect.js entry). -->
</body>
</html>
  1. Erstellen src/redirect.js (Entry Point für Webpack):
import { broadcastResponseToMainFrame } from "@azure/msal-browser/redirect-bridge";

broadcastResponseToMainFrame().catch((error) => {
    console.error("Error broadcasting response:", error);
});
  1. Update webpack.config.js:
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
    entry: {
        main: "./src/index.js",
        redirect: "./src/redirect.js", // ← Redirect bridge entry
    },
    plugins: [
        new HtmlWebpackPlugin({
            filename: "index.html",
            template: "./src/index.html",
            chunks: ["main"],
        }),
        new HtmlWebpackPlugin({
            filename: "redirect.html",
            template: "./src/redirect.html",
            chunks: ["redirect"], // ← Only include the redirect chunk
        }),
    ],
};

Next.js

Next.js Seiten werden automatisch zu Routen, sodass die Umleitungsbrücke eine Seitenkomponente ist. Das Setup unterscheidet sich zwischen dem Pages Router und dem App-Router.

Pages Router (pages/)

  1. Erstellen pages/redirect.js:
import { useEffect } from "react";
import { broadcastResponseToMainFrame } from "@azure/msal-browser/redirect-bridge";

export default function Redirect() {
    useEffect(() => {
        broadcastResponseToMainFrame().catch((error) => {
            console.error("Error broadcasting response to main frame:", error);
        });
    }, []);

    return <p>Processing authentication...</p>;
}
  1. Ausschließen der Umleitungsseite von MsalProvider in _app.js:
// pages/_app.js
import { useRouter } from "next/router";
import { MsalProvider } from "@azure/msal-react";

function MyApp({ Component, pageProps }) {
    const router = useRouter();

    // The redirect page must NOT be wrapped in MsalProvider
    if (router.pathname === "/redirect") {
        return <Component {...pageProps} />;
    }

    return (
        <MsalProvider instance={msalInstance}>
            <Component {...pageProps} />
        </MsalProvider>
    );
}

App-Router (app/)

  1. Erstellen app/redirect/page.js — dies muss eine Clientkomponente sein ("use client"):
"use client";

import { useEffect } from "react";
import { broadcastResponseToMainFrame } from "@azure/msal-browser/redirect-bridge";

export default function Redirect() {
    useEffect(() => {
        broadcastResponseToMainFrame().catch((error) => {
            console.error("Error broadcasting response to main frame:", error);
        });
    }, []);

    return <p>Processing authentication...</p>;
}
  1. Ausschließen der Umleitungsroute von MsalProvider in Ihrem Stammlayout. Wenn Ihr app/layout.js untergeordnete Elemente in MsalProvider einbettet, erstellen Sie ein separates Layout für die Redirect-Route, das dies überspringt:
// app/redirect/layout.js — no MsalProvider wrapper
export default function RedirectLayout({ children }) {
    return <>{children}</>;
}

Dadurch wird verhindert, dass MSAL den Hash der Authentifizierungsantwort verarbeitet, bevor broadcastResponseToMainFrame() ausgeführt wird.


Für beide Router sind keine next.config.js Änderungen erforderlich – Next.js stellt Seiten automatisch bereit.

Beispiel: Ein Beispiel für einen Pages Router finden Sie im nextjs-Beispiel .

Express.js / Node.js Backend

Wenn Sie Express.js verwenden (oder ein beliebiges Node.js-Backend, das statische Dateien ausliefert), konfigurieren Sie den Server so, dass er die Weiterleitungsseite ohne COOP-Header ausliefert:

const express = require("express");
const path = require("path");
const app = express();

// Serve the redirect bridge page WITHOUT COOP headers
app.get("/redirect", (req, res) => {
    res.sendFile(path.join(__dirname, "public", "redirect.html"));
});

// Set COOP headers for all other routes
app.use((req, res, next) => {
    res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
    next();
});

app.use(express.static(path.join(__dirname, "public")));

Beispiel: Siehe "HybridSample".

Zusätzliche Ressourcen