我使用两个不同的客户端。 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;
});
任何帮助都会有用。
答案 0 :(得分:3)
只要您处于同一个浏览器会话中,并且您的应用具有相同的权限(使用相同的Identity Server),这将无效。
我将向您解释原因 - 一旦您从第一个客户端登录,Identity Server就会创建一个cookie(包含所需的所有相关数据)。
现在是第二个客户端 - 权限(Identity Server)与发布cookie的权限相同。因此,Identity Server会识别您的会话,发现您已经过身份验证,并将您重定向到第二个客户端,而无需请求凭据。
毕竟,这就是Identity Server的想法:
IdentityServer4是ASP.NET Core 2的OpenID Connect和OAuth 2.0框架。
它可以在您的应用程序中启用以下功能:
身份验证即服务
所有应用程序(Web,本机,移动设备,服务)的集中登录逻辑和工作流程。 IdentityServer是OpenID Connect的官方认证实现。
单点登录/退出
在多种应用程序类型上单点登录(和退出)。
以及更多....
您必须为每个客户端寻找不同的权限(Identity Server实例),或者在这种情况下重新认为Identity Server是适合您的解决方案。
不推荐
我不建议这样做,因为它有点超越了身份服务器的SSO理念,但是如果你仍然想要这样做 - 如果你覆盖IProfileService
,你可以实现你想要的。有一个方法public Task IsActiveAsync(IsActiveContext context)
,此上下文有一个属性IsActive
,用于确定当前主体在当前客户端中是否处于活动状态。
您可以尝试在此处实现一些自定义逻辑,并根据用户ID(context.Subject.GetSubjectId()
)和客户端ID(context.Client.ClientId
)来确定用户是否已登录此客户端。
修改强>
在你的评论之后 - 这是来自Identity Server的OOTB(如果我可以这样说),但幸运的是你有一个选择。
每个客户Policy based authorization。像这样,您的用户可以对Identity Server(及其所有客户端)进行身份验证,但只有特定客户端授权他。您可以将此策略视为自定义授权属性(或多或少)。
像这样,用户将在未经授权的客户端接收未授权。希望这能清除事情并帮助:)