Skonfiguruj stronę pośredniczącą przekierowania w MSAL Browser

Ten przewodnik zawiera instrukcje specyficzne dla struktury dotyczące konfigurowania strony pomostowej przekierowania wprowadzonej w MSAL Browser w wersji 5. Aby dowiedzieć się, dlaczego mostek przekierowania jest potrzebny, zobacz przewodnik migracji z wersji 4 do wersji 5.

Warning

Strona mostka przekierowania nie może być obsługiwana z nagłówkami Cross-Origin-Opener-Policy . Strona pośrednicząca odbiera odpowiedź uwierzytelnienia po zakończeniu przepływu OAuth przez dostawcę tożsamości (IdP). Jeśli na stronie pośredniczącej ustawiono nagłówki COOP, przeglądarka dokonuje zamiany grupy kontekstów przeglądania, co zrywa kanał komunikacji z główną aplikacją — ponownie powodując dokładnie ten problem, który ta strona pośrednicząca ma rozwiązać.

Ważna

Po zaktualizowaniu swojego elementu redirectUri, aby wskazywał nową stronę pośredniczącą przekierowania, MUSISZ również zaktualizować identyfikator URI przekierowania w rejestracji aplikacji Entra ID. Identyfikator URI musi być dokładnie zgodny — łącznie ze ścieżką, protokołem i portem. Brak aktualizacji rejestracji aplikacji spowoduje błędy redirect_uri_mismatch.

Angular

  1. Utwórz komponent przekierowujący typu bridge (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. /redirect Dodaj trasę w konfiguracji routingu. Trasa przekierowania musi znajdować się pozaMsalGuard, a strona przekierowania nie powinna wykonywać wywołań API, które uruchomiłyby MsalInterceptor (ani w inny sposób wywoływać interfejsów API biblioteki MSAL):
import { RedirectComponent } from "./redirect/redirect.component";

const routes: Routes = [
    { path: "redirect", component: RedirectComponent },
    // ... your other routes
];
  1. Upewnij się, że kompilacja zawiera ten komponent. Nie jest potrzebna żadna zmiana zasobów angular.json podczas korzystania z komponentu trasy Angular — Angular CLI automatycznie dołącza ten komponent do pakietu. Jeśli wolisz statyczny redirect.html zamiast komponentu routowanego, dodaj go do tablicy `assets`:
// angular.json
{
    "projects": {
        "your-app": {
            "architect": {
                "build": {
                    "options": {
                        "assets": [
                            { "glob": "**/*", "input": "public" },
                            "src/redirect.html" // ← Add redirect bridge page
                        ]
                    }
                }
            }
        }
    }
}

Przykładowe: Zobacz angular-standalone-sample i angular-modules-sample.

Vite

Vite wymaga konfiguracji dla wielu stron, aby uwzględnić redirect.html jako osobny punkt wejścia w wynikach kompilacji.

  1. Utwórz redirect.html w katalogu głównym projektu (obok pozycji 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. Zaktualizuj vite.config.ts aby dodać stronę przekierowania jako drugi wpis:
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
            },
        },
    },
});

Podczas programowania (vite dev) strona przekierowania jest automatycznie obsługiwana pod adresem /redirect.html. W kompilacjach produkcyjnych Rollup generuje w katalogu wyjściowym zarówno index.html, jak i redirect.html.

Przykład: Zobacz przykład react-router-sample, typescript-sample i b2c-sample.

Webpack

Webpack wymaga dedykowanego punktu wejścia oraz instancji HtmlWebpackPlugin dla strony przekierowania.

  1. Utwórz 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. Utwórz src/redirect.js (punkt wejścia dla pakietu WebPack):
import { broadcastResponseToMainFrame } from "@azure/msal-browser/redirect-bridge";

broadcastResponseToMainFrame().catch((error) => {
    console.error("Error broadcasting response:", error);
});
  1. Aktualizacja 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

Strony w Next.js automatycznie stają się trasami, więc komponent strony obsługujący przekierowanie pełni rolę pomostu przekierowania. Konfiguracja różni się między routerem stron a routerem aplikacji.

Router stron (pages/)

  1. Utwórz 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. Wyklucz stronę przekierowującą z MsalProvider w _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>
    );
}

Router aplikacji (app/)

  1. Utworzyć app/redirect/page.js — musi to być składnik klienta ("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. Wyklucz ścieżkę przekierowania z MsalProvider w układzie głównym. Jeśli app/layout.js opakowuje elementy podrzędne w MsalProvider, utwórz oddzielny układ dla trasy przekierowania, który go pomija:
// app/redirect/layout.js — no MsalProvider wrapper
export default function RedirectLayout({ children }) {
    return <>{children}</>;
}

Zapobiega to przetwarzaniu przez MSAL skrótu odpowiedzi uwierzytelniającej, zanim zostanie uruchomione broadcastResponseToMainFrame().


W przypadku obu routerów nie są wymagane żadne next.config.js zmiany — Next.js automatycznie obsługuje strony.

Przykład: Zobacz nextjs-sample jako przykład routera Pages.

zaplecze Express.js/Node.js

W przypadku korzystania z Express.js (lub dowolnego Node.js zaplecza obsługującego pliki statyczne) skonfiguruj serwer tak, aby obsługiwał stronę przekierowania bez nagłówków COOP:

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")));

Przykładowe: Zobacz przykład HybridSample.

Dodatkowe zasoby