Configurer la page de pont de redirection dans MSAL Browser

Ce guide fournit des instructions spécifiques à l’infrastructure pour configurer la page de pont de redirection introduite dans MSAL Browser v5. Pour plus d’informations sur la raison pour laquelle le pont de redirection est nécessaire, consultez le guide de migration v4 vers v5.

Warning

La page intermédiaire de redirection ne doit PAS être servie avec des en-têtes Cross-Origin-Opener-Policy. La page de transition sert d’intermédiaire et reçoit la réponse d’authentification une fois que l’IdP a terminé le flux OAuth. Si des en-têtes COOP sont définis sur la page intermédiaire, le navigateur effectue un basculement de groupe de contextes de navigation qui rompt le canal de communication avec l’application principale, réintroduisant ainsi précisément le problème que ce pont est censé résoudre.

Important

Après avoir mis à jour votre redirectUri pour qu’il pointe vers la nouvelle page de pont de redirection, vous DEVEZ également mettre à jour l’URI de redirection dans votre inscription d’application dans Entra ID. L’URI doit correspondre exactement , y compris le chemin, le protocole et le port. Le fait de ne pas mettre à jour l’enregistrement de l’application entraînera des erreurs redirect_uri_mismatch.

Angular

  1. Créez le composant de pont de redirection (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. Ajoutez l’itinéraire /redirect dans votre configuration de routage. La route de redirection doit être en dehors de la MsalGuard, et la page de redirection ne doit pas effectuer d’appels d’API qui déclencheraient MsalInterceptor (ou invoqueraient autrement les API MSAL) :
import { RedirectComponent } from "./redirect/redirect.component";

const routes: Routes = [
    { path: "redirect", component: RedirectComponent },
    // ... your other routes
];
  1. Vérifiez que la build inclut le composant. Aucune modification des ressources n’est angular.json nécessaire lors de l’utilisation d’un composant de routage Angular . L’interface CLI Angular regroupe automatiquement le composant. Si vous préférez un composant statique redirect.html au lieu d’un composant routé, ajoutez-le au tableau de ressources :
// angular.json
{
    "projects": {
        "your-app": {
            "architect": {
                "build": {
                    "options": {
                        "assets": [
                            { "glob": "**/*", "input": "public" },
                            "src/redirect.html" // ← Add redirect bridge page
                        ]
                    }
                }
            }
        }
    }
}

Échantillon: Consultez angular-standalone-sample et angular-modules-sample.

Vite

Vite nécessite une configuration multi-page afin que redirect.html soit inclus comme point d’entrée distinct dans le résultat de la compilation.

  1. Créer redirect.html dans la racine de votre projet (en regard de 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. Mettre à jour vite.config.ts pour ajouter la page de redirection en tant que deuxième entrée :
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
            },
        },
    },
});

Lors du développement (vite dev), la page de redirection est automatiquement servie à l’adresse /redirect.html. Dans les builds de production, Rollup émet à la fois index.html et redirect.html dans le répertoire de sortie.

Échantillon: Consultez l’exemple react-router-sample, typescript-sample et b2c-sample.

Webpack

Webpack nécessite un point d’entrée dédié et une HtmlWebpackPlugin instance pour la page de redirection.

  1. Créer 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. Créer src/redirect.js (point d’entrée pour Webpack) :
import { broadcastResponseToMainFrame } from "@azure/msal-browser/redirect-bridge";

broadcastResponseToMainFrame().catch((error) => {
    console.error("Error broadcasting response:", error);
});
  1. Mise à jour 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 pages deviennent automatiquement des itinéraires. Le pont de redirection est donc un composant de page. La configuration diffère entre le routeur de pages et le routeur d’application.

Routeur de pages (pages/)

  1. Créer 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. Exclure la page de redirection de 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. Créer app/redirect/page.js — il doit s’agir d’un composant client ("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. Exclure l’itinéraire de redirection de MsalProvider dans votre disposition racine. Si votre app/layout.js encapsule les éléments enfants dans MsalProvider, créez une mise en page distincte pour la route de redirection qui l’ignore :
// app/redirect/layout.js — no MsalProvider wrapper
export default function RedirectLayout({ children }) {
    return <>{children}</>;
}

Cela empêche MSAL de traiter le hachage de la réponse d’authentification avant l’exécution de broadcastResponseToMainFrame().


Aucune next.config.js modification n’est nécessaire pour aucun des deux routeurs — Next.js génère automatiquement les pages.

Exemple : Consultez nextjs-sample pour voir un exemple de Pages Router.

serveur principal Express.js /Node.js

Lorsque vous utilisez Express.js (ou tout Node.js back-end servant des fichiers statiques), configurez le serveur pour qu’il serve la page de redirection sans en-têtes 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")));

Échantillon: Consultez hybridSample.

Ressources additionnelles