如何将IdentityServer4身份映射到任何WebApp(.Net MVC样板,.Net核心样板) [英] How to map IdentityServer4 Identity to any WebApp (.Net MVC Boilerplate, .Net Core Boilerplate)

查看:86
本文介绍了如何将IdentityServer4身份映射到任何WebApp(.Net MVC样板,.Net核心样板)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个SSO服务器,以将所有用户集中在ActiveDirectory(AD)中,并在那里管理它们,而不是每个特定应用程序的数据库.

I'm creating an SSO server, to centralize all users in ActiveDirectory(AD) and manage them there instead of the database of each specific application.

要制造此服务器,我将IdentityServer4(Idsr4)与 Ldap/AD扩展

To made this server I used IdentityServer4(Idsr4) with Ldap/AD Extension

我已将Idsr4设置为使用基于AD的身份(这是集中身份"),并且用户现在可以使用自己的AD登录名/密码登录Idsr4

I've setted the Idsr4 to use identity based on AD (this is "centralized identity"), and users now can login on Idsr4 with own AD login/ password

现在的问题是如何将集中式身份映射到应用程序.我想在多个应用程序中使用同一身份用户.

The question now is how to map the centralized identity to applications. I want to use same identity user in several applications.

我通读了IdentityServer4的文档,但找不到与所建议的结构相关的任何内容.

I read through the documentation of IdentityServer4 but could not find anything related to a proposed structure.

有人有清晰的结构设置可用于了解整个设置吗? (如Asp.Net MVC Boilerplate,IdentityServer4,受保护的Api之类的分隔.)

Does anybody have a clear structure setup which could be used to understand the whole setup? (Separation like Asp.Net MVC Boilerplate, IdentityServer4, Protected Api.)

IdentityServer4配置:

IdentityServer4 Config:

 public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();

        // configure identity server with in-memory stores, keys, clients and scopes
        services.AddIdentityServer()
            .AddDeveloperSigningCredential()
            ////.AddSigningCredential(...) // Strongly recommended, if you want something more secure than developer signing (Read The Manual since it's highly recommended)
            .AddInMemoryIdentityResources(InMemoryInitConfig.GetIdentityResources())
            .AddInMemoryApiResources(InMemoryInitConfig.GetApiResources())
            .AddInMemoryClients(InMemoryInitConfig.GetClients())
            .AddLdapUsers<OpenLdapAppUser>(Configuration.GetSection("IdentityServerLdap"), UserStore.InMemory);
    }

IdentityServer4 InMemoryInitConfig:

IdentityServer4 InMemoryInitConfig:

namespace QuickstartIdentityServer{
public class InMemoryInitConfig
{
    // scopes define the resources in your system
    public static IEnumerable<IdentityResource> GetIdentityResources()
    {
        return new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Profile(),
        };
    }

    public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource>
        {
            new ApiResource("api1", "My API")
        };
    }

    // clients want to access resources (aka scopes)
    public static IEnumerable<Client> GetClients()
    {
        // client credentials client
        return new List<Client>
        {
            
            //DEMO HTTP CLIENT
            new Client
            {
                ClientId = "demo",
                ClientSecrets = new List<Secret> {new Secret("password".Sha256()) } ,
                ClientName = "demo",
                AllowedGrantTypes = {
                    GrantType.ClientCredentials, // Server to server
                    GrantType.ResourceOwnerPassword, // User to server
                    GrantType.Implicit
                },

                //GrantTypes.HybridAndClientCredentials,
                AllowAccessTokensViaBrowser = true,

                AllowOfflineAccess = true,
                AccessTokenLifetime = 90, // 1.5 minutes
                AbsoluteRefreshTokenLifetime = 0,
                RefreshTokenUsage = TokenUsage.OneTimeOnly,
                RefreshTokenExpiration = TokenExpiration.Sliding,
                UpdateAccessTokenClaimsOnRefresh = true,
                RequireConsent = false,

                RedirectUris = {
                    "http://localhost:6234/"
                },

                PostLogoutRedirectUris = { "http://localhost:6234" },
                AllowedCorsOrigins ={ "http://localhost:6234/" },

                AllowedScopes =
                {
                    IdentityServerConstants.StandardScopes.OpenId,
                    IdentityServerConstants.StandardScopes.Profile,
                    "api1"
                },
                
            },

            

        };
    }
}

}

我的客户端配置:

public void Configuration(IAppBuilder app)

    {
        
        app.UseAbp();

        app.UseOAuthBearerAuthentication(AccountController.OAuthBearerOptions);

        // ABP
        //app.UseCookieAuthentication(new CookieAuthenticationOptions
        //{
        //    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        //    LoginPath = new PathString("/Account/Login"),
        //    // evaluate for Persistent cookies (IsPermanent == true). Defaults to 14 days when not set.
        //    //ExpireTimeSpan = new TimeSpan(int.Parse(ConfigurationManager.AppSettings["AuthSession.ExpireTimeInDays.WhenPersistent"] ?? "14"), 0, 0, 0),
        //    //SlidingExpiration = bool.Parse(ConfigurationManager.AppSettings["AuthSession.SlidingExpirationEnabled"] ?? bool.FalseString)
        //    ExpireTimeSpan = TimeSpan.FromHours(12),
        //    SlidingExpiration = true
        //});
        // END ABP

        /// IDENTITYSERVER
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "Cookies"
        });

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {
            Authority = "http://localhost:5443", //ID Server
            ClientId = "demo",
            ClientSecret = "password",
            ResponseType = "id_token token",
            SignInAsAuthenticationType = "Cookies",
            RedirectUri = "http://localhost:6234/", //URL of website when cancel login on idsvr4
            PostLogoutRedirectUri = "http://localhost:6234", //URL Logout ??? << when this occor
            Scope = "openid",
            RequireHttpsMetadata = false,

            //AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,

        });
        /// END IDENTITYSERVER

        app.UseExternalSignInCookie("Cookies");
        
        app.MapSignalR();
    }


更新

我正在阅读有关OpenID Connect的文档,发现可以为httpContext创建通知,以便在Idsrv4 userinfo端点中接受用户的声明,如下所示:


UPDATE

I was reading the documentation on OpenID Connect and saw that it is possible to create notifications for httpContext to take the user's claims in the Idsrv4 userinfo endpoint like this:

public void Configuration(IAppBuilder app)

    {
        
        app.UseAbp();

        // ABP
        //app.UseOAuthBearerAuthentication(AccountController.OAuthBearerOptions);

        //app.UseCookieAuthentication(new CookieAuthenticationOptions
        //{
        //    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        //    LoginPath = new PathString("/Account/Login"),
        //    // evaluate for Persistent cookies (IsPermanent == true). Defaults to 14 days when not set.
        //    //ExpireTimeSpan = new TimeSpan(int.Parse(ConfigurationManager.AppSettings["AuthSession.ExpireTimeInDays.WhenPersistent"] ?? "14"), 0, 0, 0),
        //    //SlidingExpiration = bool.Parse(ConfigurationManager.AppSettings["AuthSession.SlidingExpirationEnabled"] ?? bool.FalseString)
        //    ExpireTimeSpan = TimeSpan.FromHours(12),
        //    SlidingExpiration = true
        //});
        // END ABP

        /// IDENTITYSERVER
        AntiForgeryConfig.UniqueClaimTypeIdentifier = Thinktecture.IdentityModel.Client.JwtClaimTypes.Subject;
        JwtSecurityTokenHandler.DefaultInboundClaimFilter.Clear();

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "Cookies"
        });

        // CONFIG OPENID
        var openIdConfig = new OpenIdConnectAuthenticationOptions
        {
            Authority = "http://localhost:5443", //ID Server
            ClientId = "demo",
            ClientSecret = "password",
            ResponseType = "id_token token",
            SignInAsAuthenticationType = "Cookies",
            RedirectUri = "http://localhost:6234/", //URL of website when cancel login on idsvr4
            PostLogoutRedirectUri = "http://localhost:6234", //URL Logout ??? << when this occor
            Scope = "openid profile api1",
            RequireHttpsMetadata = false,
            
            // get userinfo
            Notifications = new OpenIdConnectAuthenticationNotifications {
                SecurityTokenValidated = async n => {
                    var userInfoClient = new UserInfoClient(
                        new Uri(n.Options.Authority + "/connect/userinfo"),
                              n.ProtocolMessage.AccessToken);

                    var userInfo = await userInfoClient.GetAsync();
                    
                    // create new identity and set name and role claim type
                    var nid = new ClaimsIdentity(
                        n.AuthenticationTicket.Identity.AuthenticationType,
                        ClaimTypes.GivenName,
                        ClaimTypes.Role);

                    foreach (var x in userInfo.Claims) {
                        nid.AddClaim(new Claim(x.Item1, x.Item2));        
                    }

                    // keep the id_token for logout
                    nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));

                    // add access token for sample API
                    nid.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken));

                    // keep track of access token expiration
                    nid.AddClaim(new Claim("expires_at", DateTimeOffset.Now.AddSeconds(int.Parse(n.ProtocolMessage.ExpiresIn)).ToString()));

                    // add some other app specific claim
                    //nid.AddClaim(new Claim("app_specific", "some data"));

                    n.AuthenticationTicket = new AuthenticationTicket(
                        nid,
                        n.AuthenticationTicket.Properties);

                    n.Request.Headers.SetValues("Authorization ", new string[] { "Bearer ", n.ProtocolMessage.AccessToken });

                }
            }

        };
        // END CONFIG OPENID

        app.UseOpenIdConnectAuthentication(openIdConfig);
        
        /// END IDENTITYSERVER

        app.UseExternalSignInCookie("Cookies");
        
        app.MapSignalR();
    }


更新2

谢谢@Khanh TO,


UPDATE 2

Thank you @Khanh TO,

我按照您的建议做了,我保留了每个应用程序的数据库

I did exactly what you recommended, I kept the database of each application

但是,我不再通过应用程序数据库来管理用户,我对从idsr4 userinfo端点获取的方法进行了硬编码

However to no longer manage the users by the application database, I hardcode a method that takes from the idsr4 userinfo endpoint

在abpUsers表中创建或更新用户所需的信息,然后应用程序解释数据并采取必要的操作

The information needed to create or update a user in the abpUsers table, then the application interprets the data and does the necessary actions

更具体地说: 在我发送给客户端AccountControllerredirect_uri中,我有一个ActionResult可以完成所有这些工作,调用在客户端userstable上创建/更新用户的必要方法

More specifically: In the redirect_uri I send to the AccountController of my client, there I have an ActionResult that does all this work calling the necessary methods to create/update an user on client userstable

推荐答案

我认为GrantType.ResourceOwnerPassword流不支持AD登录,也不被UseOpenIdConnectAuthentication都不支持,您可以使用ImplicitHybrid流.
在对客户端mvc应用进行身份验证后,您可以在HttpContext.User中查看任何声明,并以用户身份找到正确的声明值(它们只是声明,而无需创建本地帐户)

I think the GrantType.ResourceOwnerPassword flow doens't support AD login and not support by the UseOpenIdConnectAuthentication neither , you can use Implicit or Hybrid flow.
Once you authenticate the to your client mvc app, you can view any claims in HttpContext.User and find the correct claim value as user's identity (they are just claims , and no need to create a local account)

这篇关于如何将IdentityServer4身份映射到任何WebApp(.Net MVC样板,.Net核心样板)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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