Configurar a página de ponte para redirecionamento no MSAL Browser

Este guia fornece instruções específicas do framework para configurar a página de ponte para redirecionamento introduzida no MSAL Browser v5. Para obter informações sobre por que a ponte de redirecionamento é necessária, consulte o guia de migração v4 para v5.

Warning

A página de ponte de redirecionamento NÃO deve ser servida com cabeçalhos Cross-Origin-Opener-Policy. A página de ponte é um intermediário que recebe a resposta de autenticação depois que o IdP conclui o fluxo OAuth. Se os cabeçalhos COOP forem definidos na página de ponte, o navegador realizará uma troca de grupo de contexto de navegação que interrompe o canal de comunicação com o aplicativo principal, reintroduzindo exatamente o problema que a ponte foi projetada para resolver.

Importante

Depois de atualizar sua redirectUri página para apontar para a nova ponte de redirecionamento, você também deve atualizar o URI de redirecionamento em seu registro de aplicativo Entra ID. O URI deve corresponder exatamente – incluindo caminho, protocolo e porta. A falha ao atualizar o registro do aplicativo resultará em redirect_uri_mismatch erros.

Angular

  1. Criar o componente de ponte de redirecionamento (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. Adicione a /redirect rota na configuração de roteamento. A rota de redirecionamento deve estar fora do MsalGuard, e a página de redirecionamento não deve fazer chamadas de API que acionariam MsalInterceptor (ou invocar APIs do MSAL):
import { RedirectComponent } from "./redirect/redirect.component";

const routes: Routes = [
    { path: "redirect", component: RedirectComponent },
    // ... your other routes
];
  1. Verifique se o build inclui o componente. Nenhuma angular.json alteração de ativos é necessária ao usar um componente de rota Angular – a CLI angular agrupa o componente automaticamente. Se você preferir um estático redirect.html em vez de um componente roteado, adicione-o à matriz de ativos:
// angular.json
{
    "projects": {
        "your-app": {
            "architect": {
                "build": {
                    "options": {
                        "assets": [
                            { "glob": "**/*", "input": "public" },
                            "src/redirect.html" // ← Add redirect bridge page
                        ]
                    }
                }
            }
        }
    }
}

Amostra: Consulte angular-standalone-sample e angular-modules-sample.

Vite

O Vite requer uma configuração multipágina para que redirect.html seja incluído como um ponto de entrada separado na saída do build.

  1. Crie redirect.html na raiz do projeto (ao lado 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. Atualização vite.config.ts para adicionar a página de redirecionamento como uma 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 o desenvolvimento (vite dev), a página de redirecionamento é atendida automaticamente em /redirect.html. Nas compilações de produção, o Rollup gera tanto index.html quanto redirect.html no diretório de saída.

Amostra: Consulte react-router-sample, typescript-sample e b2c-sample.

Webpack

O Webpack requer um ponto de entrada dedicado e uma HtmlWebpackPlugin instância para a página de redirecionamento.

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

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

As páginas do Next.js se tornam rotas automaticamente, portanto a bridge de redirecionamento é um componente de página. A configuração difere entre o Roteador de Páginas e o Roteador de Aplicativo.

Roteador de Páginas (pages/)

  1. Criar 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 a página de redirecionamento de MsalProvider em _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>
    );
}

Roteador de Aplicativo (app/)

  1. Criar app/redirect/page.js — este deve ser um componente do 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. No layout raiz, exclua a rota de redirecionamento de MsalProvider Se o seu app/layout.js envolver os elementos filhos em MsalProvider, crie um layout separado para a rota de redirecionamento que ignore isso:
// app/redirect/layout.js — no MsalProvider wrapper
export default function RedirectLayout({ children }) {
    return <>{children}</>;
}

Isso impede que a MSAL processe o hash da resposta de autenticação antes que broadcastResponseToMainFrame() seja executado.


Nenhuma next.config.js alteração é necessária para qualquer roteador — Next.js serve páginas automaticamente.

Amostra: Consulte o exemplo de nextjs para um exemplo do Roteador de Páginas.

Back-end Express.js/Node.js

Ao usar o Express.js (ou qualquer backend em Node.js que sirva arquivos estáticos), configure o servidor para servir a página de redirecionamento sem cabeçalhos 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")));

Amostra: Consulte o HybridSample.

Recursos adicionais