IdentityServer4分别对每个客户端进行身份验证 [英] IdentityServer4 authenticate each client separately

查看:1209
本文介绍了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;
    });

任何帮助都是有用的.

解决方案

只要您在同一个浏览器会话中,并且您的应用具有相同的权限(使用相同的Identity Server),此操作就不会起作用. /p>

我将向您解释原因-从第一个客户端登录后,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(及其所有客户端)进行身份验证,但是只有特定的客户端会对其进行授权.您可以将此策略视为自定义授权属性(或多或少).

像这样,用户将在未经授权的客户端中收到未经授权的信息.希望这可以解决问题并帮助:)

I use two different clients. The IdentityServer4 provides API protections and log in form. Can I configure clients to avoid single sign on. I mean that even if I logged in the first client I need to log in the second client too.

My ID4 configuration:

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;
    });
}

All client have the same register code (Maybe it is a problem):

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;
    });

any help will be useful.

解决方案

As long as you are in the same browser session, and your apps are having the same authority (are using the same Identity Server) this will not work.

I'll explain you why - once you log in from the first client, Identity Server creates a cookie (with all the relevant data needed in it).

Now comes the second client - the authority (the Identity Server) is the same that has issued the cookie. So Identity Server recognizes your session, sees that you are already authenticated and redirects you to the second client, without asking for credentials.

After all, this is the idea of Identity Server:

IdentityServer4 is an OpenID Connect and OAuth 2.0 framework for ASP.NET Core 2.

It enables the following features in your applications:

Authentication as a Service

Centralized login logic and workflow for all of your applications (web, native, mobile, services). IdentityServer is an officially certified implementation of OpenID Connect.

Single Sign-on / Sign-out

Single sign-on (and out) over multiple application types.

and more....

This is from the official documentation.

You have to either go for different authorities (Identity Server instances) for each client, or re-think is Identity Server the right solution for you in this case.

NOT RECOMMENDED

I'm not recommending this, because it kind of overrides the SSO idea of Identity Server, however if you still want to do it then - you can achieve what you want if you override the IProfileService. There is a method public Task IsActiveAsync(IsActiveContext context) and this context has a property IsActive which determines if the current principal is active in the current client.

You can try and implement some custom logic here, and based on the user ID (context.Subject.GetSubjectId()) and the client id (context.Client.ClientId) to determine if the user is already logged in this client or not.

EDIT

After your comment - this is something that doesn't come OOTB from Identity Server (if I can say it like this), but luckily you have an option.

Policy based authorization per client. Like this, your user can authenticate against Identity Server (and all of its clients), but only the specific clients will authorize him. You can treat this policies as a custom authorize attribute (more or less).

Like this, a user will receive unauthorized in clients, where he.. is not authorized. Hope that this clears the thing and helps :)

这篇关于IdentityServer4分别对每个客户端进行身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆