Как выйти из сервера Blazor без Microsoft.Identity.Web.UI?

Я знаю, что мой следующий вопрос очень связан с этим: существующий вопрос но ответ не решает мою проблему и, возможно, есть что-то еще.

Итак, у меня есть веб-приложение blazor в .net 8, использующее рендеринг на стороне сервера. Я хочу выполнить вход и выход из системы единого входа, используя Azure Entra Id (активный каталог) с OpenIdConnect.

Подпишите, работает нормально, но с выходом у меня больше проблем. Как я могу сделать это без вызов перенаправления на Navigation.NavigateTo("MicrosoftIdentity/Account/SignOut", true);. Я не хочу использовать Microsoft.Identity.Web.UI, потому что не хочу создавать страницы в своем приложении, если в этом нет необходимости. Я не управляю пользователями из приложения.

Я попытался выйти из системы, используя что-то вроде этого:

NavigationManager.NavigateTo("https://login.microsoftonline.com/{tenantid}/oauth2/logout?post_logout_redirect_uri=https://localhost:7216/signout-oidc");

или

var request = httpContextAccessor.HttpContext.Request;
logoutRedirectUri = "https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri = " + Uri.EscapeDataString(request.Scheme + Uri.SchemeDelimiter + request.Host + request.PathBase + "/signout-oidc");
NavigationManager.NavigateTo(logoutRedirectUri, true);

Меня перенаправляют на https://localhost:7216/signout-oidc — пустую страницу. Если я попытаюсь перенаправить его «/» (домашняя страница), я автоматически войдусь в систему.

Это то, что я настроил, а также ссылки зарегистрированы при регистрации приложения на портале Azure.

  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "ClientId": "{clientId}",
    "TenantId": "{tenantid}",
    "CallbackPath": "/signin-oidc",
    "SignedOutCallbackPath": "/signout-oidc"
}

Изменить – Полный код:

Программа.cs

 var builder = WebApplication.CreateBuilder(args);

builder.Services.AddMudServices(config =>
{
    config.SnackbarConfiguration.PositionClass = Defaults.Classes.Position.TopRight;
    config.SnackbarConfiguration.PreventDuplicates = false;
    config.SnackbarConfiguration.NewestOnTop = true;
    config.SnackbarConfiguration.ShowCloseIcon = true;
    config.SnackbarConfiguration.VisibleStateDuration = 7000;
    config.SnackbarConfiguration.HideTransitionDuration = 500;
    config.SnackbarConfiguration.ShowTransitionDuration = 500;
    config.SnackbarConfiguration.SnackbarVariant = Variant.Outlined;
});

builder.Services.AddDbContextFactory<Context>(options =>
{
    options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
});


//Looger
builder.Logging.AddAzureWebAppDiagnostics();
builder.Logging.AddApplicationInsights(
    configureTelemetryConfiguration: (config) =>
        config.ConnectionString = builder.Configuration.GetConnectionString("AppInsights"),
    configureApplicationInsightsLoggerOptions: (options) => { }
    );

//SSO Login
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApp(options =>
    {
        // Bind the configuration section and set additional options
        builder.Configuration.Bind("AzureAd", options);
       
    });

builder.Services.AddAuthorization(options =>
{
   
    options.AddPolicy("AdminOnly", policy => policy.RequireRole("Admin"));
    options.AddPolicy("UserOnly", policy => policy.RequireRole("User"));
});

builder.Services.AddScoped<NotificationToastUtility>();
builder.Services.AddControllersWithViews();
builder.Services.AddRazorPages();


builder.Services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
Registration.AddRegistration(builder.Services);

// Add SignalR services
builder.Services.AddSignalR();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
   
    app.UseExceptionHandler("/Error", createScopeForErrors: true);
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();
app.UseAntiforgery();

app.UseAuthentication();
app.UseAuthorization();



app.MapRazorComponents<App>()
    .AddInteractiveServerRenderMode();
app.MapRazorPages();
app.MapControllers();

// Map the SignalR hub
app.MapHub<StepHub>("/stephub");

app.Run();

В панели навигации у меня есть ссылка, которая вызывает выход из системы.

 <a href = "@logoutRedirectUri"><span class = "oi oi-account-logout">Logout</span></a>

Код создания @logoutRedirectUri

 protected override void OnInitialized()
 {
     var request = httpContextAccessor.HttpContext.Request;

     var loginHint = request.HttpContext.User.FindFirstValue("login_hint");

     logoutRedirectUri = "https://login.microsoftonline.com/common/oauth2/v2.0/logout?post_logout_redirect_uri = "
         + Uri.EscapeDataString(request.Scheme + Uri.SchemeDelimiter + request.Host + request.PathBase + "/signout-oidc");

     if (loginHint != null)
     {
         logoutRedirectUri += "&logout_hint = " + Uri.EscapeDataString(loginHint);
     }
 }
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
168
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Существует два уровня выхода из системы:

  1. Выйдите из своего приложения. Обычно это делается для очистки файлов cookie аутентификации.

  2. Выход из системы единого входа (Microsoft Entra ID), который выполнит выход из всех приложений. Это делается путем перенаправления на https://login.microsoftonline.com/common/oauth2/v2.0/logout.

Я не хочу использовать Microsoft.Identity.Web.UI, потому что не хочу создавать страницы в своем приложении, если в этом нет необходимости. Я не управляю пользователями из приложения.

Пакет Microsoft.Identity.Web.UI предназначен не для управления пользователями, а для управления состоянием аутентификации.

Например, очистка файлов cookie аутентификации в вашем приложении или отображение страницы выхода из системы.

Если у вас нет страницы выхода с анонимным доступом, вы автоматически будете перенаправлены на страницу входа, где вы можете автоматически войти снова.

вам следует проверить исходный код: https://github.com/AzureAD/microsoft-identity-web/tree/master/src/Microsoft.Identity.Web.UI/Areas/MicrosoftIdentity


Если вы не хотите использовать Microsoft.Identity.Web.UI, вам придется создать собственную страницу/контроллер для его обработки. Посмотрите действие /MicrosoftIdentity/Account/SignOut:

    /// <summary>
    /// Handles the user sign-out.
    /// </summary>
    /// <param name = "scheme">Authentication scheme.</param>
    /// <returns>Sign out result.</returns>
    [HttpGet("{scheme?}")]
    public IActionResult SignOut(
        [FromRoute] string scheme)
    {
        if (AppServicesAuthenticationInformation.IsAppServicesAadAuthenticationEnabled)
        {
            if (AppServicesAuthenticationInformation.LogoutUrl != null)
            {
                return LocalRedirect(AppServicesAuthenticationInformation.LogoutUrl);
            }
            return Ok();
        }
        else
        {
            scheme ??= OpenIdConnectDefaults.AuthenticationScheme;
            var callbackUrl = Url.Page("/Account/SignedOut", pageHandler: null, values: null, protocol: Request.Scheme);
            return SignOut(
                 new AuthenticationProperties
                 {
                     RedirectUri = callbackUrl,
                 },
                 CookieAuthenticationDefaults.AuthenticationScheme,
                 scheme);
        }
    }

Ответ возврата SignOut() творит здесь чудеса, но вы можете вручную очистить файлы cookie и потенциально перенаправить на страницу выхода из системы единого входа.

Другие вопросы по теме

Могу ли я использовать Azure Data Explorer (Kusto) для запроса данных (например, групп) в Microsoft Entra Admin Center?
Как я могу использовать пользователя, вошедшего в систему tEdge, для входа в приложение React?
Невозможно создать и использовать токен для использования ACS для пользователя команды: «CallAgent должен быть создан только с токеном ACS»
Ошибка AuthenticationContext с MFA AADTS50076
Клиенту службы Microsoft Graph не удается ИСПРАВИТЬ пользовательские атрибуты безопасности
Невозможно использовать личную электронную почту с API Graph после установки идентификатора арендатора на «общий»
Создание общего API для доступа к любому BLOB-объекту в любой учетной записи хранения в клиенте
Azure AD B2C — разделение проверки электронной почты и установка пароля на два экрана
Межклиентское хранилище BLOB-объектов Azure SAS завершается сбоем с сообщением «Подпись не соответствует» с использованием UserDelegatedCredential и azure-sdk-for-go
Как получить клиент Microsoft Graph в веб-приложении ASP.NET Core?