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 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 estiverem definidos na página de redirecionamento, o navegador realiza uma troca de grupo de contexto de navegação que interrompe o canal de comunicação de volta para o aplicativo principal — reintroduzindo exatamente o problema que a ponte foi projetada para resolver.

Importante

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

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 do Angular — a CLI do 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. Em builds de produção, o Rollup emite ambos os index.html e 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 ponte 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. Exclua a rota de redirecionamento de MsalProvider no seu layout raiz. Se o seu app/layout.js envolver filhos em MsalProvider, crie um layout separado para a rota de redirecionamento que a ignore:
// 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