Configurar la página de enlace para la redirección en MSAL Browser

En esta guía se proporcionan instrucciones específicas del marco para configurar la página del puente de redirección introducida en MSAL Browser v5. Para obtener información sobre por qué se necesita el puente de redirección, consulte la guía de migración de v4 a v5.

Warning

La página del puente de redireccionamiento NO debe servirse con encabezados Cross-Origin-Opener-Policy. La página del puente es un intermediario que recibe la respuesta de autenticación después de que el IdP complete el flujo de OAuth. Si se establecen encabezados COOP en la página puente, el navegador realiza un cambio de grupo de contexto de navegación que interrumpe el canal de comunicación con la aplicación principal, reintroduciendo exactamente el problema que el puente está diseñado para resolver.

Importante

Después de actualizar redirectUri para que apunte a la nueva página del puente de redireccionamiento, también DEBE actualizar el URI de redireccionamiento en el registro de la aplicación de Entra ID. El URI debe coincidir exactamente , incluida la ruta de acceso, el protocolo y el puerto. No actualizar el registro de la aplicación provocará errores redirect_uri_mismatch.

Angular

  1. Cree el componente de puente de redirección (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. Agrega la ruta /redirect en tu configuración de enrutamiento. La ruta de redireccionamiento debe estar fuera de MsalGuard, y la página de redireccionamiento no debe realizar llamadas a la API que desencadenen MsalInterceptor (ni invocar de otro modo las API de MSAL):
import { RedirectComponent } from "./redirect/redirect.component";

const routes: Routes = [
    { path: "redirect", component: RedirectComponent },
    // ... your other routes
];
  1. Asegúrese de que la compilación incluye el componente . No angular.json se necesita ningún cambio de recursos cuando se usa un componente de ruta de Angular: la CLI de Angular agrupa el componente automáticamente. Si prefiere un elemento estático redirect.html en lugar de un componente enrutado, agréguelo a la matriz assets:
// angular.json
{
    "projects": {
        "your-app": {
            "architect": {
                "build": {
                    "options": {
                        "assets": [
                            { "glob": "**/*", "input": "public" },
                            "src/redirect.html" // ← Add redirect bridge page
                        ]
                    }
                }
            }
        }
    }
}

Ejemplo: Consulte angular-standalone-sample y angular-modules-sample.

Vite

Vite requiere una configuración de varias páginas para que redirect.html se incluya como punto de entrada independiente en la salida de la compilación.

  1. Crear redirect.html en la raíz del proyecto (junto a 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. Actualizar vite.config.ts para agregar la página de redireccionamiento como segunda entrada:
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
            },
        },
    },
});

Durante el desarrollo (vite dev), la página de redireccionamiento se sirve automáticamente en /redirect.html. En las compilaciones de producción, Rollup genera tanto index.html como redirect.html en el directorio de salida.

Ejemplo: Consulte react-router-sample, typescript-sample y b2c-sample.

Webpack

Webpack requiere un punto de entrada dedicado y una HtmlWebpackPlugin instancia para la página de redirección.

  1. Crear 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. Crear src/redirect.js (punto de entrada para Webpack):
import { broadcastResponseToMainFrame } from "@azure/msal-browser/redirect-bridge";

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

Las páginas de Next.js pasan a ser rutas automáticamente, por lo que el puente para la redirección es un componente de página. La configuración difiere entre el enrutador de páginas y el enrutador de aplicaciones.

Enrutador de páginas (pages/)

  1. Crear 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. Excluir la página de redireccionamiento de MsalProvider en _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>
    );
}

Enrutador de aplicaciones (app/)

  1. Crear app/redirect/page.js : debe ser un componente de cliente ("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. Excluir la ruta de redireccionamiento de MsalProvider en el diseño raíz. Si su app/layout.js envuelve elementos hijo en MsalProvider, cree un diseño independiente para la ruta de redireccionamiento que lo omita:
// app/redirect/layout.js — no MsalProvider wrapper
export default function RedirectLayout({ children }) {
    return <>{children}</>;
}

Esto impide que MSAL procese el hash de respuesta de autenticación antes broadcastResponseToMainFrame() de ejecutarse.


No next.config.js se necesitan cambios en ninguno de los enrutadores: Next.js sirve las páginas automáticamente.

Ejemplo: Consulte el ejemplo nextjs-sample para ver un ejemplo de Enrutador de páginas.

Back-end de Express.js/Node.js

Al usar Express.js (o cualquier Node.js back-end que atiende archivos estáticos), configure el servidor para atender la página de redirección sin encabezados 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")));

Ejemplo: Consulte HybridSample.

Recursos adicionales