.NET Core 应用程序(带有 Auth0)在 IIS 8 上托管时短 session/logout

.NET Core app (with Auth0) has short session/logout when hosted on IIS 8

(我 post 在 Auth0 Forum 上编辑了同样的消息,但我也在此处询问,以防这不是身份验证问题。)

我有一个 .NET Core 应用程序使用 Auth0 的身份验证 API 对 Active Directory 用户进行身份验证。所有这些都按预期工作。当我 运行 来自 Visual Studio 2015 的应用程序并在我的浏览器中打开它时,它似乎记得我以前的登录并且不会重定向我重新登录一段时间 (有效可能是 JWT 的长度?).

当应用发布到 Windows Server 2012 上的 IIS 时,用户会在大约 20 分钟不活动后注销。

到目前为止,我的研究使我找到了有关更改 IIS 中应用程序池设置以允许更长会话的文章。我忍不住想也许有更好的方法,通过重新检查 cookie 或其他东西。我很乐意 post 我的 Startup.cs 文件中的代码或其他任何可能有用的代码。

是否可以使用 OIDC/cookie 中间件自动重新验证用户身份而不是延长 IIS 会话时间?如果最好的做法是延长会话,请随时告诉我。

任何能为我指明正确方向的提示都将不胜感激。谢谢!

更新(代码片段)

这里有一些代码可供查看!我需要另一双眼睛。

这是我在 Startup.cs 中的 ConfigureServices 方法:

public void ConfigureServices(IServiceCollection services)
{
    services.AddRouting(options => options.LowercaseUrls = true);

    // Add authentication services
    services.AddAuthentication(
        options => options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme);

    services.AddScoped<IMyRepository, MyRepository>();

    // Add framework services.
    services.AddMvc(config =>
    {
        var policy = new AuthorizationPolicyBuilder()
                        .RequireAuthenticatedUser()
                        .Build();
        config.Filters.Add(new AuthorizeFilter(policy));

        if (_env.IsProduction())
        {
            config.Filters.Add(new RequireHttpsAttribute());
        }
    });

    // Add functionality to inject IOptions<T>
    services.AddOptions();

    // Add the Auth0 Settings object so it can be injected
    services.Configure<Auth0Settings>(Configuration.GetSection("Auth0"));
}

这是我的 Configure 方法:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IOptions<Auth0Settings> auth0Settings)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
        app.UseBrowserLink();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();

    // Add the cookie middleware
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AutomaticAuthenticate = true,
        AutomaticChallenge = true
    });

    // Add the OIDC middleware
    var options = new OpenIdConnectOptions("Auth0")
    {
        // Set the authority to our Auth0 domain
        Authority = $"https://{auth0Settings.Value.Domain}",

        // Configure the Auth0 Client ID and Client Secret
        ClientId = auth0Settings.Value.ClientId,
        ClientSecret = auth0Settings.Value.ClientSecret,

        // Do not automatically authenticate and challenge
        AutomaticAuthenticate = false,
        AutomaticChallenge = false,

        // Set response type to code
        ResponseType = "code",

        // Set the callback path, so Auth0 will call back to http://localhost:5000/signin-auth0
        // Also ensure that you have added the URL as an Allowed Callback URL in your Auth0 dashboard
        CallbackPath = new PathString("/signin-auth0"),

        // Configure the Claims issuer to be Auth0
        ClaimsIssuer = "Auth0",

        Events = new OpenIdConnectEvents
        {
            OnRedirectToIdentityProvider = context =>
            {
                if (context.Properties.Items.ContainsKey("connection"))
                    context.ProtocolMessage.SetParameter("connection", context.Properties.Items["connection"]);

                return Task.FromResult(0);
            }
        }
    };
    options.Scope.Clear();
    options.Scope.Add("openid");
    options.Scope.Add("name");
    options.Scope.Add("email");
    options.Scope.Add("groups");
    options.Scope.Add("roles");
    app.UseOpenIdConnectAuthentication(options);

    app.UseMvc(routes =>
    {
        routes.MapRoute(
            name: "default",
            template: "{controller=Customer}/{action=Index}/{id?}");
    });
}

为了更好的衡量,这是我在帐户控制器中的 Login 方法:

[AllowAnonymous]
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel vm, string returnUrl = null)
{
    if (ModelState.IsValid)
    {
        try
        {
            AuthenticationApiClient client = new AuthenticationApiClient(new Uri($"https://{_auth0Settings.Domain}"));

            var result = await client.AuthenticateAsync(new AuthenticationRequest
            {
                ClientId = _auth0Settings.ClientId,
                Scope = "openid name email groups",
                Connection = "<trimmed>",
                Username = vm.Username,
                Password = vm.Password
            });

            // Get user info from token
            var user = await client.GetTokenInfoAsync(result.IdToken);

            // Create claims principal
            var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new[]
            {
                new Claim(ClaimTypes.NameIdentifier, user.UserId),
                new Claim(ClaimTypes.Name, user.FullName),
                new Claim(ClaimTypes.Email, user.Email)
            }, CookieAuthenticationDefaults.AuthenticationScheme));

            // Sign user in to cookie middleware **LOOK**
            await HttpContext.Authentication.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);

            return RedirectToLocal(returnUrl);
        }
        catch (ApiException ex)
        {
            // trimmed...
        }
        catch (Exception ex)
        {
            // trimmed...
        }
    }
    return View(vm);
}

在我的网络服务器上 运行 .NET Core provisioning script 之后,我能够让它工作。 (感谢 .NET Core Slack 频道上的 @pinpoint 帮我解决了这个问题!)

在我的服务器上实现更好的日志记录有助于快速确认问题。我在 SerilogSerilog.Sinks.RollingFile 包上取得了很好的成功。

经过身份验证的 cookie 现在可以正确保存,甚至可以在应用程序池回收后继续存在。