错误:Azure AD 身份验证 Web 应用程序中的内部服务器错误部署为 Azure Web 应用程序服务中的 docker 容器

问题描述

我有带有 azure 广告身份验证的 aspnet 核心 2.1 Web 应用程序。当我以调试模式在本地运行我的应用程序时,一切都按预期工作。而当我在登录后在 azure web 应用程序服务(Linux、Docker)中部署我的 web 应用程序时,它会引发内部服务器错误 500“xxxx.azurewebsites.net 当前无法处理此请求。” 下面是我的startup.cs和appsettings.json供参考

{ "Authentication": { "ClientId": "my client Id",
"Authority": "https://login.microsoftonline.com/我的租户 ID/",
"PostlogoutRedirectUri": "http://localhost:44372",
"CallbackPath": "/signin-oidc","ClientSecret": "","ResponseType": "code id_token" } }

using System;
using System.Threading.Tasks;
using Core2AadAuth.Filters;
using Core2AadAuth.Options;
using Core2AadAuth.Services;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.IdentityModel.Clients.ActiveDirectory;

namespace Core2AadAuth
{
  public class Startup
  {
    public Startup(IConfiguration configuration)
    {
      Configuration = configuration;
    }

    private IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
      services.AddMvc(opts =>
      {
        opts.Filters.Add(typeof(AdalTokenAcquisitionExceptionFilter));
      }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

      //Todo: Set up Data Protection key persistence correctly for your env: https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview?tabs=aspnetcore2x
      //I go with defaults,which works fine in my case
      //But if you run on Azure App Service and use deployment slots,keys get swapped with the app
      //So you'll need to setup storage for keys outside the app,Key Vault and Blob Storage are some options
      services.AddDataProtection();

      //Add a strongly-typed options class to DI
      services.Configure<AuthOptions>(Configuration.GetSection("Authentication"));

      services.AddScoped<ITokenCacheFactory,TokenCacheFactory>();

      services.AddAuthentication(auth =>
      {
        auth.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        auth.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
      })
      .AddCookie()
      .AddOpenIdConnect(opts =>
      {
        Configuration.GetSection("Authentication").Bind(opts);
        opts.Events = new OpenIdConnectEvents
        {
          OnRedirectToIdentityProvider = async n =>
          {
            n.ProtocolMessage.RedirectUri = "https://xxxxx.azurewebsites.net/signin-oidc";
            await Task.CompletedTask;
          },OnAuthorizationCodeReceived = async ctx =>
                {
                HttpRequest request = ctx.HttpContext.Request;
                      //We need to also specify the redirect URL used
                      string currentUri = UriHelper.BuildAbsolute(request.Scheme,request.Host,request.PathBase,request.Path);
                      //Credentials for app itself
                      var credential = new ClientCredential(ctx.Options.ClientId,ctx.Options.ClientSecret);

                      //Construct token cache
                      ITokenCacheFactory cacheFactory = ctx.HttpContext.RequestServices.GetrequiredService<ITokenCacheFactory>();
                TokenCache cache = cacheFactory.CreateForUser(ctx.Principal);

                var authContext = new AuthenticationContext(ctx.Options.Authority,cache);

                      //Get token for Microsoft Graph API using the authorization code
                      string resource = "https://graph.microsoft.com";
                AuthenticationResult result = await authContext.AcquiretokenByAuthorizationCodeAsync(
                          ctx.ProtocolMessage.Code,new Uri(currentUri),credential,resource);

                      //Tell the OIDC middleware we got the tokens,it doesn't need to do anything
                      ctx.HandleCodeRedemption(result.Accesstoken,result.IdToken);
              }
        };
      });

      services.Configure<HstsOptions>(o =>
      {
        o.IncludeSubDomains = false;
        o.Preload = false;
        o.MaxAge = TimeSpan.FromDays(365);
      });
    }

    public void Configure(IApplicationBuilder app,IHostingEnvironment env)
    {
      if (env.IsDevelopment())
      {
        app.UseDeveloperExceptionPage();
      }
      else
      {
        //Outside dev,require HTTPS and use HSTS
        app.UseHttpsRedirection();
        app.UseHsts();
      }



      app.UseStaticFiles();

      app.UseAuthentication();

      app.UseMvcWithDefaultRoute();
    }
  }
}

Error after login

2021-05-02T09:33:20.315827397Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost1 2021-05-02T09:33:20.315907498Z 请求开始 HTTP/1.1 GET http://mwp4.azurewebsites.net/ 2021-05-02T09:33:20.608016175Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3] 2021-05-02T09:33:20.608738579Z 路由匹配 {action = “索引”,控制器 =“主页”}。执行控制器动作 控制器上的签名 Microsoft.AspNetCore.Mvc.IActionResult Index() Core2AadAuth.Controllers.HomeController (Core2AadAuth)。 2021-05-02T09:33:20.745331263Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker1 2021-05-02T09:33:20.745368864Z 执行动作方法 Core2AadAuth.Controllers.HomeController.Index (Core2AadAuth) - 验证状态:有效 2021-05-02T09:33:20.755374821Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2] 2021-05-02T09:33:20.755394921Z 执行的动作方法 Core2AadAuth.Controllers.HomeController.Index (Core2AadAuth),返回 结果 Microsoft.AspNetCore.Mvc.ViewResult 在 0.8199 毫秒内。 2021-05-02T09:33:20.831668759Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor1 2021-05-02T09:33:20.831702459Z 执行 ViewResult,正在运行 查看索引。

2021-05-02T09:33:21.814197839Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.ViewFeatures.ViewResultExecutor[4] 2021-05-02T09:33:21.814222039Z 执行 ViewResult - 查看索引 在 1012.1419 毫秒内执行。 2021-05-02T09:33:21.814531541Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2] 2021-05-02T09:33:21.814560341Z 已执行操作 Core2AadAuth.Controllers.HomeController.Index (Core2AadAuth) 中 1186.6101ms 2021-05-02T09:33:21.834760456Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost[2] 2021-05-02T09:33:21.834786356Z 请求在 1554.1302 毫秒内完成 200 文本/html;字符集=utf-8 2021-05-02T09:33:24.456892780Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost1 2021-05-02T09:33:24.456933081Z 请求开始 HTTP/1.1 GET http://mwp4.azurewebsites.net/Account/SignIn
2021-05-02T09:33:24.459599695Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[3] 2021-05-02T09:33:24.459617195Z 路由匹配 {action = “登录”,控制器 =“帐户”}。执行控制器动作 签名 Microsoft.AspNetCore.Mvc.IActionResult SignIn() on 控制器 Core2AadAuth.Controllers.AccountController (Core2AadAuth)。 2021-05-02T09:33:24.459623195Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker1 2021-05-02T09:33:24.459628095Z 执行动作方法 Core2AadAuth.Controllers.AccountController.SignIn (Core2AadAuth) - 验证状态:有效 2021-05-02T09:33:24.459632395Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2] 2021-05-02T09:33:24.459636995Z 执行的动作方法 Core2AadAuth.Controllers.AccountController.SignIn (Core2AadAuth),在 0.634 毫秒内返回结果 Microsoft.AspNetCore.Mvc.ChallengeResult。 2021-05-02T09:33:24.476765988Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.ChallengeResult1 2021-05-02T09:33:24.476797989Z 执行 ChallengeResult 身份验证方案 ()。 2021-05-02T09:33:25.925815616Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[12] 2021-05-02T09:33:25.925878418Z 认证方案: OpenIdConnect 受到挑战。 2021-05-02T09:33:25.947421249Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2] 2021-05-02T09:33:25.947478451Z 已执行操作 Core2AadAuth.Controllers.AccountController.SignIn (Core2AadAuth) 中 1488.4947ms 2021-05-02T09:33:25.965321140Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost[2] 2021-05-02T09:33:25.965363141Z 请求在 1500.8083 毫秒内完成 302

2021-05-02T09:33:29.811005026Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost1 2021-05-02T09:33:29.811039125Z 请求开始 HTTP/1.1 POST http://mwp4.azurewebsites.net/signin-oidc 应用程序/x-www-form-urlencoded 2784 2021-05-02T09:33:29.905246546Z [40m[1m[33mwarn[39m[22m[49m: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[15] 2021-05-02T09:33:29.905324345Z
'.AspNetCore.Correlation.OpenIdConnect.NKdEqhMMORt61fYDDm70J3AyzqpUmgMxsYxaQfuygWI' 未找到 cookie。 2021-05-02T09:33:29.906978817Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[4] 2021-05-02T09:33:29.906995617Z 远程身份验证错误: 关联失败.. 2021-05-02T09:33:29.976640649Z [41m[30mfail[39m[22m[49m: Microsoft.AspNetCore.Server.Kestrel[13]] 2021-05-02T09:33:29.976668449Z 连接 ID“0HM8D9L7PD097”, 请求 ID“0HM8D9L7PD097:00000001”:抛出未处理的异常 通过应用程序。 2021-05-02T09:33:29.976674549Z System.Exception: 处理远程登录时遇到错误。 ---> System.Exception:关联失败。 2021-05-02T09:33:29.976679149Z
--- 内部异常堆栈跟踪结束 --- 2021-05-02T09:33:29.976691948Z at Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler1.HandleRequestAsync() 2021-05-02T09:33:29.976696448Z at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) 2021-05-02T09:33:29.976700648Z at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context) 2021-05-02T09:33:29.976705048Z at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication1 申请)2021-05-02T09:33:29.976709248Z [40m[32minfo[39m[22m[49m: Microsoft.AspNetCore.Hosting.Internal.WebHost[2] 2021-05-02T09:33:29.976713648Z 请求在 157.9686 毫秒内完成 500

解决方法

一个原因可能是您没有跨部署保留数据保护密钥环。当数据保护 API 密钥环丢失时,会生成一组新的密钥,现有的 cookie 将不再有效。用于加密 cookie 的密钥在各个部署中必须相同。

我之前在博客中介绍了一种方法:

另见page