IdentityServer4 аутентифицирует каждого клиента отдельно
Я использую два разных клиента. IdentityServer4 обеспечивает защиту API и форму входа в систему. Могу ли я настроить клиентов, чтобы избежать единого входа. Я имею в виду, что даже если я вошел в первый клиент, мне нужно войти и во второй клиент.
Моя конфигурация ID4:
internal static IEnumerable<Client> GetClients(IEnumerable<RegisteredClient> clients)
{
return clients.Select(x =>
{
var scopes = x.AllowedScopes.ToList();
scopes.Add(IdentityServerConstants.StandardScopes.OpenId);
scopes.Add(IdentityServerConstants.StandardScopes.Profile);
scopes.Add(IdentityServerConstants.StandardScopes.OfflineAccess);
var client = new Client
{
ClientId = x.Id,
ClientName = x.Name,
AllowedGrantTypes = GrantTypes.Hybrid,
RequireConsent = false,
RefreshTokenExpiration = TokenExpiration.Sliding,
RefreshTokenUsage = TokenUsage.ReUse,
ClientSecrets = {new Secret(x.Secret.Sha256())},
RedirectUris = new[] {$"{x.Url}/signin-oidc"},
PostLogoutRedirectUris = new[] {$"{x.Url}/signout-callback-oidc"},
UpdateAccessTokenClaimsOnRefresh = true,
AllowAccessTokensViaBrowser = true,
AllowedScopes = scopes,
AllowedCorsOrigins = {x.Url},
AllowOfflineAccess = true
};
return client;
});
}
Все клиенты имеют одинаковый код регистрации (возможно, это проблема):
const string oidcScheme = "oidc";
const string coockieScheme = CookieAuthenticationDefaults.AuthenticationScheme;
services.AddAuthentication(options =>
{
options.DefaultScheme = coockieScheme;
options.DefaultChallengeScheme = oidcScheme;
})
.AddCookie(coockieScheme)
.AddOpenIdConnect(oidcScheme, options =>
{
options.SignInScheme = coockieScheme;
options.Authority = identitySettings.Authority;
options.RequireHttpsMetadata = false;
options.ClientId = identitySettings.Id;
options.ClientSecret = identitySettings.Secret;
options.ResponseType = "code id_token";
options.Scope.Add("offline_access");
foreach (var scope in identitySettings.Scopes)
{
options.Scope.Add(scope);
}
options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
});
любая помощь будет полезна.
2 ответа
Пока вы находитесь в одном сеансе браузера и ваши приложения имеют одинаковые полномочия (используют один и тот же Identity Server), это не будет работать.
Я объясню вам, почему - как только вы входите в систему с первого клиента, Identity Server создает файл cookie (со всеми необходимыми данными, необходимыми для него).
Теперь приходит второй клиент - полномочия (Identity Server) те же, что выдал cookie. Таким образом, Identity Server распознает ваш сеанс, видит, что вы уже прошли проверку подлинности, и перенаправляет вас на второй клиент, не запрашивая учетные данные.
В конце концов, это идея Identity Server:
IdentityServer4 является платформой OpenID Connect и OAuth 2.0 для ASP.NET Core 2.
Он включает следующие функции в ваших приложениях:
Аутентификация как услуга
Централизованная логика входа и рабочий процесс для всех ваших приложений (веб, нативные, мобильные, сервисы). IdentityServer является официально сертифицированной реализацией OpenID Connect.
Единый вход / выход
Единый вход (и выход) для нескольких типов приложений.
и больше....
Это из официальной документации.
Вы должны либо использовать разные полномочия (экземпляры Identity Server) для каждого клиента, либо заново подумать, является ли Identity Server подходящим решением для вас в этом случае.
НЕ РЕКОМЕНДУЕТСЯ
Я не рекомендую это, потому что это как бы отвергает идею единого входа в Identity Server, однако, если вы все еще хотите это сделать - вы можете достичь того, чего хотите, если переопределите IProfileService
, Есть метод public Task IsActiveAsync(IsActiveContext context)
и этот контекст имеет свойство IsActive
который определяет, является ли текущий участник активным в текущем клиенте.
Вы можете попробовать и реализовать некоторую пользовательскую логику здесь, и на основе идентификатора пользователя (context.Subject.GetSubjectId()
) и идентификатор клиента (context.Client.ClientId
), чтобы определить, вошел ли пользователь в данный клиент или нет.
РЕДАКТИРОВАТЬ
После вашего комментария - это что-то, что не приходит OOTB от Identity Server (если я могу так сказать), но, к счастью, у вас есть возможность.
Политика на основе авторизации для каждого клиента. Таким образом, ваш пользователь может проходить аутентификацию на Identity Server (и на всех его клиентах), но только определенные клиенты будут авторизовывать его. Вы можете рассматривать эту политику как настраиваемый атрибут авторизации (более или менее).
Таким образом, пользователь будет получать неавторизованные на клиентах, где он.. не авторизован. Надеюсь, что это проясняет дело и помогает:)
Вы можете установить
prompt=login
от всех ваших клиентов.
prompt
none - no UI will be shown during the request. If this is not possible (e.g. because the user has to sign in or consent) an error is returned
login - the login UI will be shown, even if the user is already signed-in and has a valid session
https://identityserver4.readthedocs.io/en/latest/endpoints/authorize.html
Это заставит второго клиента снова войти в систему независимо от статуса входа в систему предыдущего клиента.