代理后面的 ASP.NET MVC 应用程序的 Azure AD 身份验证问题:缺少 .AspNet.Cookies Cookie

问题描述 投票:0回答:1

我有一个旧版 ASP.NET 4.8 MVC 应用程序,正在将其迁移为使用 Microsoft.Owin 框架的 Azure AD 身份验证。应用程序配置在我的本地计算机上运行良好。但是,我在生产服务器上运行它时遇到了问题。

生产环境代理设置:应用程序托管在代理后面的 IIS 服务器上。 SSL 在代理处终止,HTTP 请求转发到 IIS 服务器。

当我在生产服务器上浏览受保护的页面时,我被正确重定向到login.microsoftonline.com登录页面并且可以成功登录。但是,登录后,生产服务器上未设置 .AspNet.Cookies 身份验证 cookie,导致应用程序和 Azure AD /authorize 端点之间出现重定向循环。

我假设发出“.AspNet.Cookies”cookie 时出现问题,因为我在浏览器中没有看到该问题。如何证实这一点?或被追踪?

这是在startup.cs类中配置的方式。我遵循了一些在线文章来实现这一点并且在我的本地运行良好。

public void Configuration(IAppBuilder app)
{
    // Configure Auth0 parameters
    string auth0Domain = ConfigurationManager.AppSettings["auth0:Domain"];
    string auth0ClientId = ConfigurationManager.AppSettings["auth0:ClientId"];
    string auth0RedirectUri = ConfigurationManager.AppSettings["auth0:RedirectUri"];
    string auth0PostLogoutRedirectUri = ConfigurationManager.AppSettings["auth0:PostLogoutRedirectUri"];

    // Set Cookies as default authentication type
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
        LoginPath = new PathString("/Account/Login"),
        CookieSameSite = Microsoft.Owin.SameSiteMode.None,
        // More information on why the CookieManager needs to be set can be found here: 
        // https://github.com/aspnet/AspNetKatana/wiki/System.Web-response-cookie-integration-issues
        CookieManager = new SameSiteCookieManager(new SystemWebCookieManager())
    });


    // Configure Auth0 authentication
    app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
    {
        AuthenticationType = "Auth0",

        Authority = auth0Domain,

        ClientId = auth0ClientId,

        RedirectUri = auth0RedirectUri,
        PostLogoutRedirectUri = auth0PostLogoutRedirectUri,
        ResponseType = OpenIdConnectResponseType.CodeIdToken,
        Scope = "openid profile email",

        SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,

        TokenValidationParameters = new TokenValidationParameters
        {
            NameClaimType = "name"
        },

        // More information on why the CookieManager needs to be set can be found here: 
        // https://docs.microsoft.com/en-us/aspnet/samesite/owin-samesite
        CookieManager = new SameSiteCookieManager(new SystemWebCookieManager()),

        Notifications = new OpenIdConnectAuthenticationNotifications
        {
            AuthorizationCodeReceived = async n =>
            {
                var client = new HttpClient();
                var tokenResponse = await client.RequestAuthorizationCodeTokenAsync(new AuthorizationCodeTokenRequest
                {
                    Code = n.Code,
                    Address = "https://login.microsoftonline.com/2d55c52b-2865-45c0-b174-fef7eed8e331/oauth2/v2.0/token",
                    ClientId = auth0ClientId,
                    ClientSecret = "WLT8Q~KKe2S5k~XrzUsz-XJUiRPdgaiBAx1uYcnr",
                    RedirectUri = auth0RedirectUri,
                });

                if (tokenResponse.IsError)
                    throw new Exception(tokenResponse.Error);

                var response = await client.GetUserInfoAsync(new UserInfoRequest
                {
                    Token = tokenResponse.AccessToken,
                    Address = "https://graph.microsoft.com/oidc/userinfo",
                });

                if (response.IsError)
                    throw new Exception(response.Error);

                n.AuthenticationTicket.Identity.AddClaims(response.Claims);
            },
            RedirectToIdentityProvider = notification =>
            {
                if (notification.ProtocolMessage.RequestType == OpenIdConnectRequestType.Authentication)
                {

                }
                if (notification.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
                {
                    var logoutUri = $"https://{auth0Domain}/v2/logout?client_id={auth0ClientId}";

                    var postLogoutUri = notification.ProtocolMessage.PostLogoutRedirectUri;
                    if (!string.IsNullOrEmpty(postLogoutUri))
                    {
                        if (postLogoutUri.StartsWith("/"))
                        {
                            // transform to absolute
                            var request = notification.Request;
                            postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase + postLogoutUri;
                        }
                        logoutUri += $"&returnTo={Uri.EscapeDataString(postLogoutUri)}";
                    }

                    notification.Response.Redirect(logoutUri);
                    notification.HandleResponse();
                }
                return Task.FromResult(0);
            }
        }
    });
}

如何确保 .AspNet.Cookies cookie 在生产服务器上正确设置?

是否需要额外的配置来处理代理处的 SSL 终止?

编辑:添加了 web.config 文件

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  https://go.microsoft.com/fwlink/?LinkId=301880
  -->
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    <section name="sdx.logging" type="SDX.Logging.SDXLoggingConfiguration, SDX.System" />
    <section name="sdx.services" type="SDX.Services.SDXServicesConfiguration, SDX.Services" />
    <section name="sdx.resources" type="SDX.Resources.SDXResourcesConfiguration, SDX.Resources" />
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
  </configSections>
  
  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="true" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    
    <add key="auth0:Domain" value="https://login.microsoftonline.com/xxxx/v2.0" />
    <add key="auth0:ClientId" value="f14563a5c4" />
    <add key="auth0:RedirectUri" value="http://localhost:49141" />
    <add key="auth0:PostLogoutRedirectUri" value="http://localhost:49141" />
  </appSettings>
  <connectionStrings>
  </connectionStrings>
  <log4net debug="true">
  <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
    <file value="logs\log.txt" />
    <appendToFile value="true" />
    <rollingStyle value="Size" />
    <maxSizeRollBackups value="10" />
    <maximumFileSize value="10MB" />
    <datePattern value="yyyyMMdd" />
    <layout type="log4net.Layout.PatternLayout">
      <conversionPattern value="%date [%thread] %-5level %logger [%ndc] – %message%newline" />
    </layout>
  </appender>

  <root>
    <level value="DEBUG" />
    <appender-ref ref="RollingLogFileAppender" />
  </root>
</log4net>
  <!--
      maxLogAgeDays = How many days of logs to keep. Max=7.
      traceLevel = 
        Error: Output error-handling messages.
        Warning: Output warnings and error-handling messages.
        Info: Output informational messages, warnings, and error-handling messages.
        Verbose: Output all debugging and tracing messages.
    -->
  <sdx.logging traceLevel="Verbose" cleanupInterval="1.00:00:00" logFilename="C:\SourceCodes\VSTS\Logs\%d\web.log">
    <cleanupDirectories>
      <add name="C:\SourceCodes\VSTS\Logs\" />
    </cleanupDirectories>
  </sdx.logging>
  
  <system.web>
    <compilation debug="true" targetFramework="4.8" />
    <httpRuntime targetFramework="4.8" />
  </system.web>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Antlr3.Runtime" publicKeyToken="eb42632606e9261f" />
        <bindingRedirect oldVersion="0.0.0.0-3.5.0.2" newVersion="3.5.0.2" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Web.Infrastructure" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-2.0.1.0" newVersion="2.0.1.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" />
        <bindingRedirect oldVersion="0.0.0.0-12.0.0.0" newVersion="12.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Optimization" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="1.1.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-1.6.5135.21930" newVersion="1.6.5135.21930" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-5.2.9.0" newVersion="5.2.9.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.IdentityModel.Logging" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-7.5.2.0" newVersion="7.5.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.IdentityModel.Tokens" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-7.5.2.0" newVersion="7.5.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.IdentityModel.JsonWebTokens" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-7.5.2.0" newVersion="7.5.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.1.2" newVersion="4.0.1.2" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Text.Encodings.Web" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.IdentityModel.Protocols" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-7.5.2.0" newVersion="7.5.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.IdentityModel.Protocols.OpenIdConnect" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-7.5.2.0" newVersion="7.5.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.IdentityModel.Tokens.Jwt" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-7.5.2.0" newVersion="7.5.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-4.2.2.0" newVersion="4.2.2.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=2.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
  </entityFramework>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="ServiceEndpointBehavior">
          <dataContractSerializer maxItemsInObjectGraph="2147483647" />
          <clientCredentials>
            <serviceCertificate>
              <authentication certificateValidationMode="None" />
            </serviceCertificate>
          </clientCredentials>
        </behavior>
        <behavior name="MyServiceBehavior">
          <enableWebScript />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
    <bindings>
      <netTcpBinding>
        <binding name="NetTcpBinding" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions" hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="2147483647" maxBufferSize="2147483647" maxConnections="10" maxReceivedMessageSize="2147483647">
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
          <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
          <security mode="None">
            <message clientCredentialType="None" />
          </security>
        </binding>
      </netTcpBinding>
    </bindings>
    <client>
      <endpoint name="NetTcpBinding_IMySampleAppService" address="net.tcp://localhost:8585/MySampleAppService" binding="netTcpBinding" bindingConfiguration="NetTcpBinding" contract="SDX.GCPS.Models.IMySampleAppService" behaviorConfiguration="ServiceEndpointBehavior">
        <identity>
          <servicePrincipalName value="hostname/localhost" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>
c# asp.net asp.net-mvc azure-active-directory owin
1个回答
0
投票

在 Web.config 中配置代理设置:

<configuration>
  <system.net>
    <defaultProxy>
      <proxy autoDetect="true" />
    </defaultProxy>
  </system.net>
</configuration>

用于 HTTP 标头转发的自定义中间件:

using System.Threading.Tasks;
using System.Web;

public class ForwardHeadersMiddleware : OwinMiddleware
{
    public ForwardHeadersMiddleware(OwinMiddleware next) : base(next) { }

    public override async Task Invoke(IOwinContext context)
    {
        var request = context.Request;
        var response = context.Response;

        // Forward the headers
        var xForwardedFor = request.Headers["X-Forwarded-For"];
        var xForwardedProto = request.Headers["X-Forwarded-Proto"];
        var xForwardedHost = request.Headers["X-Forwarded-Host"];

        if (!string.IsNullOrEmpty(xForwardedFor))
        {
            response.Headers.Set("X-Forwarded-For", xForwardedFor);
        }

        if (!string.IsNullOrEmpty(xForwardedProto))
        {
            response.Headers.Set("X-Forwarded-Proto", xForwardedProto);
        }

        if (!string.IsNullOrEmpty(xForwardedHost))
        {
            response.Headers.Set("X-Forwarded-Host", xForwardedHost);
        }

        await Next.Invoke(context);
    }
}
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.