Я знаю, что мой следующий вопрос очень связан с этим: существующий вопрос но ответ не решает мою проблему и, возможно, есть что-то еще.
Итак, у меня есть веб-приложение 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);
}
}





Существует два уровня выхода из системы:
Выйдите из своего приложения. Обычно это делается для очистки файлов cookie аутентификации.
Выход из системы единого входа (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 и потенциально перенаправить на страницу выхода из системы единого входа.