Я разрабатываю приложение в ASP.NET Core 2.1 и запускаю его в кластере Kubernetes.Я реализовал аутентификацию, используя OpenIDConnect, используя Auth0 в качестве моего провайдера.
Это все работает нормально.Действия или контроллеры, помеченные атрибутом [Authorize]
, перенаправляют анонимного пользователя на провайдера идентификации, они входят в систему, перенаправляют обратно, и Боб - твой дядя.
Проблемы начинают возникать, когда я масштабирую свое развертывание до 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 является его устойчивость испособность очень хорошо справляться с масштабированием.В существующем состоянии я могу масштабировать только свои вспомогательные службы, и мое основное приложение должно работать как один модуль.Это далеко от идеала.
Возможно, где-то есть механизм, который создает сходство с конкретным экземпляром, о котором я не знаю?
Надеюсь, кто-то может указать мне правильное направление.
Спасибо!