.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 帮我解决了这个问题!)
在我的服务器上实现更好的日志记录有助于快速确认问题。我在 Serilog 和 Serilog.Sinks.RollingFile
包上取得了很好的成功。
经过身份验证的 cookie 现在可以正确保存,甚至可以在应用程序池回收后继续存在。
(我 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 帮我解决了这个问题!)
在我的服务器上实现更好的日志记录有助于快速确认问题。我在 Serilog 和 Serilog.Sinks.RollingFile
包上取得了很好的成功。
经过身份验证的 cookie 现在可以正确保存,甚至可以在应用程序池回收后继续存在。