IdentityServer4分别对每个客户端进行身份验证

par*_*ix2 4 authentication single-sign-on identityserver4 asp-net-core-spa-services

我使用两个不同的客户端。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;
    });
}
Run Code Online (Sandbox Code Playgroud)

所有客户端都有相同的注册码(也许这是一个问题):

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;
    });
Run Code Online (Sandbox Code Playgroud)

任何帮助都会有用的。

m3n*_*ak3 5

只要您位于同一浏览器会话中,并且您的应用程序具有相同的权限(使用相同的身份服务器),这将不起作用。

我将向您解释原因 - 一旦您从第一个客户端登录,Identity Server 就会创建一个 cookie(其中包含所需的所有相关数据)。

现在出现了第二个客户端 - 权威机构(身份服务器)与发布 cookie 的机构相同。因此,Identity Server 会识别您的会话,发现您已经通过身份验证,并将您重定向到第二个客户端,而不要求提供凭据。

毕竟,这就是Identity Server的想法:

IdentityServer4 是适用于 ASP.NET Core 2 的 OpenID Connect 和 OAuth 2.0 框架。

它在您的应用程序中启用以下功能:

身份验证即服务

所有应用程序(Web、本机、移动、服务)的集中登录逻辑和工作流程。IdentityServer 是 OpenID Connect 的官方认证实现。

单点登录/退出

在多种应用程序类型上进行单点登录(和退出)。

和更多....

这是来自官方文档

您必须为每个客户端选择不同的权限(Identity Server 实例),或者重新考虑 Identity Server 在这种情况下是否是适合您的解决方案。

不建议

我不推荐这样做,因为它有点覆盖了 Identity Server 的 SSO 想法,但是如果您仍然想这样做 - 如果您覆盖IProfileService. 有一个方法public Task IsActiveAsync(IsActiveContext context),并且此上下文有一个属性IsActive,可以确定当前主体在当前客户端中是否处于活动状态。

您可以尝试在此处实现一些自定义逻辑,并根据用户 ID ( context.Subject.GetSubjectId()) 和客户端 ID ( context.Client.ClientId) 来确定用户是否已登录此客户端。

编辑

在您发表评论之后 - 这不是来自 Identity Server 的 OOTB(如果我可以这样说的话),但幸运的是您有一个选择。

每个客户端基于策略的授权。像这样,您的用户可以针对 Identity Server(及其所有客户端)进行身份验证,但只有特定的客户端才会授权他。您可以将此策略视为自定义授权属性(或多或少)。

像这样,用户将在客户端中收到未经授权的信息,而他..未获得授权。希望这能解决问题并有所帮助:)