Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом руководстве приведены инструкции для конкретных фреймворков по настройке страницы-посредника для перенаправления, введённой в MSAL Browser v5. Сведения о том, почему требуется мост перенаправления, см. в руководстве по миграции версии 4 до версии 5.
Предупреждение
Страница моста перенаправления не должна обслуживаться заголовками Cross-Origin-Opener-Policy . Страница-посредник — это промежуточная страница, которая получает ответ аутентификации после того, как IdP завершает поток OAuth. Если на странице моста заданы заголовки COOP, браузер выполняет смену группы контекстов просмотра, что разрывает канал связи с основным приложением, — тем самым вновь создавая ту самую проблему, которую мост и предназначен решать.
Important
После обновления redirectUri так, чтобы он указывал на новую страницу моста перенаправления, обязательно также обновите URI перенаправления в регистрации вашего приложения Entra ID.
Универсальный код ресурса (URI) должен соответствовать точно — включая путь, протокол и порт.
Если не обновить регистрацию приложения, это приведет к ошибкам redirect_uri_mismatch.
Angular
-
Создайте компонент моста перенаправления (
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);
});
}
}
-
/redirectДобавьте маршрут в конфигурацию маршрутизации. Маршрут перенаправления должен находиться внеMsalGuard, а страница перенаправления не должна выполнять вызовы API, которые могли бы вызватьMsalInterceptor(или иным образом вызывать API MSAL):
import { RedirectComponent } from "./redirect/redirect.component";
const routes: Routes = [
{ path: "redirect", component: RedirectComponent },
// ... your other routes
];
- Убедитесь, что сборка включает компонент. При
angular.jsonиспользовании компонента маршрута Angular не требуется никаких изменений. Интерфейс командной строки Angular автоматически объединяет компонент. Если вы предпочитаете статическийredirect.htmlвместо компонента, связанного с маршрутом, добавьте его в массив assets:
// angular.json
{
"projects": {
"your-app": {
"architect": {
"build": {
"options": {
"assets": [
{ "glob": "**/*", "input": "public" },
"src/redirect.html" // ← Add redirect bridge page
]
}
}
}
}
}
}
Образец: См. пример angular-standalone-sample и angular-modules-sample.
Vite
Для Vite требуется многостраничная конфигурация, чтобы redirect.html был включён в результат сборки как отдельная точка входа.
-
Создать
redirect.htmlв корневом каталоге проекта (рядом с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>
-
Обновите
vite.config.ts, чтобы добавить страницу перенаправления в качестве второй записи:
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
},
},
},
});
Во время разработки (vite dev) страница перенаправления автоматически доступна по адресу /redirect.html. В production-сборках Rollup создает в выходном каталоге и index.html, и redirect.html.
Образец: См. пример react-router-sample, typescript-sample и b2c-sample.
Webpack
Webpack требует отдельной точки входа и экземпляра HtmlWebpackPlugin для страницы перенаправления.
-
Создать
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>
-
Создать
src/redirect.js(точка входа для Webpack):
import { broadcastResponseToMainFrame } from "@azure/msal-browser/redirect-bridge";
broadcastResponseToMainFrame().catch((error) => {
console.error("Error broadcasting response:", error);
});
-
Обновление
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 Router и App Router.
Маршрутизатор страниц (pages/)
-
Создать
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>;
}
-
Исключите страницу перенаправления из
MsalProviderв_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/)
-
Создать
app/redirect/page.js— это должен быть клиентский компонент ("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>;
}
-
Исключите маршрут перенаправления из
MsalProviderв корневом макете. Если вашapp/layout.jsоборачивает дочерние элементы вMsalProvider, создайте отдельный макет для маршрута перенаправления, в котором он не используется:
// app/redirect/layout.js — no MsalProvider wrapper
export default function RedirectLayout({ children }) {
return <>{children}</>;
}
Это не позволяет MSAL обрабатывать хэш ответа аутентификации до запуска broadcastResponseToMainFrame().
Изменения next.config.js не требуются для любого маршрутизатора— Next.js автоматически обслуживает страницы.
Пример: См. nextjs-sample для примера с Pages Router.
Серверная часть на Express.js / Node.js
При использовании Express.js (или любого другого бэкенда на Node.js, отдающего статические файлы) настройте сервер так, чтобы страница перенаправления отдавалась без заголовков 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")));
Пример: См. раздел HybridSample.