[英]Validate authentication cookie with ASP.NET Core 2.1 / 3+ Identity
[英]ASP.NET Core 2.1 cookie authentication appears to have server affinity
我正在ASP.NET Core 2.1中開發一個應用程序,並在Kubernetes集群上運行它。 我使用OpenIDConnect實現了身份驗證,使用Auth0作為我的提供者。
一切正常。 標有[Authorize]
屬性的操作或控制器將匿名用戶重定向到身份提供者,他們登錄,重定向回來,Bob是你的叔叔。
當我將部署擴展到2個或更多容器時,問題就開始出現了。 當用戶訪問應用程序時,他們會登錄,並且根據回調期間服務的容器,身份驗證成功或失敗。 即使在身份驗證成功的情況下,當用戶點擊未經授權的容器時,重復F5-ing最終也會重定向到身份提供者。
我對此的想法是,使用cookie身份驗證,用戶將cookie存儲在他們的瀏覽器中,隨每個請求一起傳遞,應用程序對其進行解碼並抓取JWT,然后是來自它的聲明,以及用戶經過身份驗證。 這使得整個事情無狀態,因此無論為請求提供服務的容器如何都應該工作。 然而,如上所述,它似乎並沒有實際工作。
我在Startup.cs
配置如下所示:
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect("Auth0", options =>
{
options.Authority = $"https://{Configuration["Auth0:Domain"]}";
options.ClientId = Configuration["Auth0:ClientId"];
options.ClientSecret = Configuration["Auth0:ClientSecret"];
options.ResponseType = "code";
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name"
};
options.SaveTokens = true;
options.CallbackPath = new PathString("/signin-auth0");
options.ClaimsIssuer = "Auth0";
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProviderForSignOut = context =>
{
var logoutUri =
$"https://{Configuration["Auth0:Domain"]}/v2/logout?client_id={Configuration["Auth0:ClientId"]}";
var postLogoutUri = context.Properties.RedirectUri;
if (!string.IsNullOrEmpty(postLogoutUri))
{
if (postLogoutUri.StartsWith("/"))
{
var request = context.Request;
postLogoutUri = request.Scheme + "://" + request.Host + request.PathBase +
postLogoutUri;
}
logoutUri += $"&returnTo={Uri.EscapeDataString(postLogoutUri)}";
}
context.Response.Redirect(logoutUri);
context.HandleResponse();
return Task.CompletedTask;
},
OnRedirectToIdentityProvider = context =>
{
context.ProtocolMessage.SetParameter("audience", "https://api.myapp.com");
// Force the scheme to be HTTPS, otherwise we end up redirecting back to HTTP in production.
// They should seriously make it easier to make Kestrel serve over TLS in the same way ngninx does...
context.ProtocolMessage.RedirectUri = context.ProtocolMessage.RedirectUri.Replace("http://",
"https://", StringComparison.OrdinalIgnoreCase);
Debug.WriteLine($"RedirectURI: {context.ProtocolMessage.RedirectUri}");
return Task.FromResult(0);
}
};
});
我花了好幾個小時試圖解決這個問題,然后空了。 我唯一能想到的就是理論上現在可以使用的是粘性負載平衡,但這比應用實際修復問題更能應用創可貼。
使用Kubernetes的主要原因之一是它的彈性和處理擴展的能力非常好。 就目前而言,我只能擴展我的支持服務,而我的主應用程序必須作為單個pod運行。 那遠非理想。
也許有某種機制可以創建與我不知道的特定實例的親和力?
我希望有人能指出我正確的方向。
謝謝!
身份驗證發出的cookie通過Data Protection加密。 默認情況下,數據保護的范圍限定為特定應用程序或其實例。 如果需要在實例之間共享auth cookie,則需要確保將數據保護密鑰持久保存到公共位置,並確保應用程序名稱相同。
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\server\share\directory\"))
.SetApplicationName("MyApp");
您可以在文檔中找到更多信息。
每當我重新啟動Azure App Service(PaaS)並且我的用戶的cookie不再有效時,我就遇到了同樣的問題。 我的應用程序使用ASP.NET Core Identity框架。
以下文檔說明了將數據保護配置為跨多個應用程序實例甚至多個Web應用程序的各種方法:
https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/configuration/overview
我發現使用blob存儲帳戶是讓它工作的最快方法:
var storageAccount = CloudStorageAccount.Parse(configuration["Configuration key to Azure storage connection string"]);
var client = storageAccount.CreateCloudBlobClient();
var container = client.GetContainerReference("key-container");
container.CreateIfNotExistsAsync().GetAwaiter().GetResult();
services.AddDataProtection()
.SetApplicationName("Application Name")
.PersistKeysToAzureBlobStorage(container, "keys.xml");
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.