简体   繁体   English

在针对 Azure AD 注销 ASP.NET Core MVC 应用程序时如何修复错误 404?

[英]How to fix error 404 when logging out on an ASP.NET Core MVC app against Azure AD?

I'm integrating an ASP.NET Core MVC 3.0 app to Azure AD for authentication and authorization adn everything works well, but when I try to sign out, once login.microsoftonline.com signs me out, it redirects to my app and then the following error springs up:我正在将 ASP.NET Core MVC 3.0 应用程序集成到 Azure AD 以进行身份​​验证和授权,一切正常,但是当我尝试注销时,一旦login.microsoftonline.com我注销,它就会重定向到我的应用程序,然后出现以下错误:

No webpage was found for the web address:

https://localhost:5002/Account/SignOut?page=%2FAccount%2FSignedOut

The path I use to invoke the signout process is /AzureAD/Account/SignOut .我用来调用注销过程的路径是/AzureAD/Account/SignOut

Contents of appsettings.json : appsettings.json内容:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "[OMITTED]",
    "TenantId": "[OMITTED]",
    "ClientId": "[OMITTED]",
    "CallbackPath": "/signin-oidc"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

These are the contents of my Startup.cs class:这些是我的Startup.cs类的内容:

using System.Collections.Generic;
using System.Globalization;
using MySite.WebSite.Helpers;
using MySite.WebSite.Models.Validators;
using MySite.WebSite.Models.ViewModels;
using FluentValidation;
using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.AzureAD.UI;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Localization;

namespace MySite.WebSite
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services
                .AddAuthentication(AzureADDefaults.AuthenticationScheme)
                .AddAzureAD(options => Configuration.Bind("AzureAd", options));

            services.Configure<CookieAuthenticationOptions>(AzureADDefaults.CookieScheme, options =>
            {
                options.AccessDeniedPath = "/Home/AccessDenied";
                options.LogoutPath = "/";
            });

            services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
            {
                options.Authority += "/v2.0/";
                options.TokenValidationParameters.ValidateIssuer = false;
            });

            services.AddLocalization(options => options.ResourcesPath = "Resources");
            services
                .AddControllersWithViews(options => options.Filters.Add(GetAuthorizeFilter()))
                .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
                .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
                .AddDataAnnotationsLocalization()
                .AddFluentValidation();

            services.AddTransient<IValidator<ContactIndexViewModel>, ContactIndexViewModelValidator>();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseRequestLocalization(GetLocalizationOptions());
            app.UseStaticFiles(GetStaticFileOptions());
            app.UseRouting();
            app.UseAuthentication();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }

        private RequestLocalizationOptions GetLocalizationOptions()
        {
            var cookie_request_culture_provider = new CookieRequestCultureProvider
            {
                CookieName = "UserCulture"
            };
            var providers = new List<IRequestCultureProvider>()
            {
                cookie_request_culture_provider,
                new AcceptLanguageHeaderRequestCultureProvider()
            };

            var result = new RequestLocalizationOptions
            {
                RequestCultureProviders = providers,
                SupportedCultures = Cultures.SupportedCultures,
                SupportedUICultures = Cultures.SupportedCultures,
                DefaultRequestCulture = new RequestCulture(Cultures.DefaultCulture)
            };
            return result;
        }

        private StaticFileOptions GetStaticFileOptions()
        {
            var result = new StaticFileOptions
            {
                ServeUnknownFileTypes = true,
                DefaultContentType = "text/plain"
            };
            return result;
        }

        private AuthorizeFilter GetAuthorizeFilter()
        {
            var policy = new AuthorizationPolicyBuilder()
                .RequireAuthenticatedUser()
                .Build();
            var result = new AuthorizeFilter(policy);
            return result;
        }
    }
}

Turns out this is a known issue in Microsoft.AspNetCore.Authentication.AzureAD.UI ;原来这是Microsoft.AspNetCore.Authentication.AzureAD.UI一个已知问题 that package implements the Azure AD authentication/authorization flow in ASP.NET Core, and part of that is an embedded AccountController (area AzureAD ) that takes the signin - signout processes out of your shoulders.该包在 ASP.NET Core 中实现了 Azure AD 身份验证/授权流程,其中一部分是嵌入式AccountController (区域AzureAD ),它可以让您AzureAD完成登录-注销过程。 Problem is, the SignOut action hardcodes a redirect to /Account/SignOut?page=%2FAccount%2FSignedOut once the signout process is complete, and there's the problem.问题是,一旦注销过程完成, SignOut操作会将重定向硬编码到/Account/SignOut?page=%2FAccount%2FSignedOut ,这就是问题所在。

I managed to solve it by implementing a small AccountController (without an area) and adding a single SignOut action that handles the redirect from Microsoft.AspNetCore.Authentication.AzureAD.UI 's AccountController :我设法通过实现一个小的 AccountController (没有区域)并添加一个处理来自Microsoft.AspNetCore.Authentication.AzureAD.UIAccountController的重定向的SignOut操作来解决它:

[AllowAnonymous]
public class AccountController : Controller
{
    [HttpGet]
    public IActionResult SignOut(string page)
    {
        return RedirectToAction("Index", "Home");
    }
}

In (at least) the latest versions you should add endpoints.MapRazorPages();在(至少)最新版本中,您应该添加endpoints.MapRazorPages(); in the Configure() method of Startup.在启动的 Configure() 方法中。 This handles the route for you.这会为您处理路线。

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller=Home}/{action=Index}/{id?}");
    endpoints.MapRazorPages();//ADD THIS LINE
});

I spent half a day chasing this down, realizing it got broken when we migrated to .NET Core 3.0.我花了半天的时间来解决这个问题,意识到当我们迁移到 .NET Core 3.0 时它被破坏了。

We also migrated to Microsoft Identity because the AzureADB2C UI was marked as obsolete.我们还迁移到 Microsoft Identity,因为 AzureADB2C UI 被标记为过时。 So, in ConfigureServices, we added:因此,在 ConfigureServices 中,我们添加了:

services.AddRazorPages()
            .AddMicrosoftIdentityUI();

...and as Paul said, in Configure we added: ...正如保罗所说,在配置中我们添加了:

endpoints.MapRazorPages();

This solved the problem for us.这为我们解决了问题。 We got the hint from creating a brand new MVC Web App with Microsoft Identity authentication from template and compared the differences in our ConfigureServices / Configure methods.我们通过从模板创建一个带有 Microsoft 身份验证的全新 MVC Web 应用程序获得了提示,并比较了我们的 ConfigureServices / Configure 方法的差异。

您必须在 _LoginPartial.cshtml 文件中将 asp-area="AzureAD"值更改为asp-area="MicrosoftIdentity"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何修复 IIS 上的 ASP.Net Core 404 错误? - How to fix ASP.Net Core 404 error on IIS? Azure 应用服务上的 ASP.NET Core MVC Azure AD 身份验证循环 - ASP.NET Core MVC Azure AD Authentication Loop on Azure App Service Azure中的ASP.NET MVC Core应用 - ASP.NET MVC Core app in Azure 如何在ASP.NET Core 2中使用依赖注入的OIDC登录Azure AD后添加自己的声明? - How to add own claims after logging in to Azure AD with OIDC in ASP.NET Core 2 with dependency injection? Azure AD 与 ASP.NET 核心 MVC 中的标识 - Azure AD with Identity in ASP.NET Core MVC 如何修复asp.net核心mvc项目中的jquery错误? - how to fix jquery error in asp.net core mvc project? 在 Azure 中部署 ASP.net 核心应用程序时,Azure AD 的 400 id 令牌无效 - 400 invalid id token for Azure AD when ASP.net core app is deployed in Azure 错误:Asp.net核心MVC中具有Azure AD身份验证的关联失败 - Error: Correlation failed in Asp.net core MVC with Azure AD authentication Asp.net Core Azure Web应用程序日志记录 - Asp.net Core azure web app logging 将 Azure AD 集成到 ASP.NET Core Web 应用程序时更改默认拒绝访问路径 - Changing default access denied path when integrating Azure AD into an ASP.NET Core web app
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM