簡體   English   中英

使用IdentityServer登錄到Identity Provider,並通過OpenID驗證用戶身份

[英]Login with Identity Provider using IdentityServer and Authenticate Users via OpenID

我是IdentityServer概念的新手,在我們如何驗證用戶身份方面需要幫助。 我有一個Web表單項目,在其中我將默認身份驗證更改為個人用戶帳戶。 已經注冊了一些用戶,並且能夠成功創建聲明並進行身份驗證。 現在,我想用OpenID身份驗證實現SSO,因此我將IdentityServer3添加到我的項目中,並在ConfigAuth方法下對Start.Auth.cs文件進行了以下更改。

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap = new Dictionary<string, string>();

        // Enable the application to use a cookie to store information for the signed in user
        // and to use a cookie to temporarily store information about a user logging in with a third party login provider
        // Configure the sign in cookie
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            }
        });

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {
            AuthenticationType = "oidc",
            SignInAsAuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            Authority = "http://localhost:52262/Core",
            ClientId = "webforms.owin.implicit",
            RedirectUri = "~/Default.aspx",
            PostLogoutRedirectUri = "~/Login.aspx",
            ResponseType = "id_token token",
            Scope = "openid profile email",
            UseTokenLifetime = false,
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                SecurityTokenValidated = async n =>
                  {
                      //var id = n.AuthenticationTicket.Identity;

                      //var sub = id.FindFirst(IdentityServer3.Core.Constants.ClaimTypes.Subject);
                      //var roles = id.FindAll(IdentityServer3.Core.Constants.ClaimTypes.Role);

                      //// create new identity and set name and role claim type
                      //var nid = new ClaimsIdentity(
                      //        id.AuthenticationType,
                      //        IdentityServer3.Core.Constants.ClaimTypes.Name
                      //        , IdentityServer3.Core.Constants.ClaimTypes.Role
                      //        );

                      //nid.AddClaim(sub);
                      //nid.AddClaims(roles);
                      //// keep the id_token for logout
                      //nid.AddClaim(new Claim("id_token", n.ProtocolMessage.IdToken));
                      //n.AuthenticationTicket = new AuthenticationTicket(
                      //    nid,
                      //    n.AuthenticationTicket.Properties);

                      //return Task.FromResult(0);


                      var claims_to_exclude = new[]
                      {
                              "aud", "iss", "nbf", "exp", "nonce", "iat", "at_hash"
                            };

                      var claims_to_keep =
                          n.AuthenticationTicket.Identity.Claims
                          .Where(x => false == claims_to_exclude.Contains(x.Type)).ToList();
                      claims_to_keep.Add(new Claim("id_token", n.ProtocolMessage.IdToken));

                      if (n.ProtocolMessage.AccessToken != null)
                      {
                          claims_to_keep.Add(new Claim("access_token", n.ProtocolMessage.AccessToken));

                          var userInfoClient = new UserInfoClient(new Uri("http://localhost:52262/core/connect/userinfo"), n.ProtocolMessage.AccessToken);
                          var userInfoResponse = await userInfoClient.GetAsync();
                          var userInfoClaims = userInfoResponse.Claims
                              .Where(x => x.Item1 != "sub") // filter sub since we're already getting it from id_token
                              .Select(x => new Claim(x.Item1, x.Item2));
                          claims_to_keep.AddRange(userInfoClaims);
                      }

                      var ci = new ClaimsIdentity(
                          n.AuthenticationTicket.Identity.AuthenticationType,
                          "name", "role");
                      ci.AddClaims(claims_to_keep);

                      n.AuthenticationTicket = new Microsoft.Owin.Security.AuthenticationTicket(
                          ci, n.AuthenticationTicket.Properties
                      );
                  },
                RedirectToIdentityProvider = n =>
                {
                    if (n.ProtocolMessage.RequestType == OpenIdConnectRequestType.Logout)
                    {
                        var id_token = n.OwinContext.Authentication.User.FindFirst("id_token")?.Value;
                        n.ProtocolMessage.IdTokenHint = id_token;
                    }

                    return Task.FromResult(0);
                }
            }
        });

        app.UseStageMarker(PipelineStage.Authenticate);

如果用戶能夠成功登錄(SignInStatus.Success :),我還添加了一些Claims轉換邏輯,該邏輯將從Login.aspx.cs文件調用。

public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {
        if (!incomingPrincipal.Identity.IsAuthenticated)
        {
            return base.Authenticate(resourceName, incomingPrincipal);
        }            
        var newPrincipal = CreateApplicationPrincipal(incomingPrincipal.Identity.Name, incomingPrincipal.Identity.GetUserId());

        EstablishSession(newPrincipal);

        return newPrincipal;
    }

    private void EstablishSession(ClaimsPrincipal newPrincipal)
    {
        var sessionToken = new SessionSecurityToken(newPrincipal, TimeSpan.FromHours(8))
        {
            IsPersistent = false, // make persistent
            IsReferenceMode = true // cache on server
        };

        FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
    }

    private ClaimsPrincipal CreateApplicationPrincipal(string name, string v)
    {
        var claims = new List<Claim>();

        if(name == "sid@test.com")
        {
            var p = Principal.Create("Application",
                new Claim(ClaimTypes.Name, name),
                new Claim(ClaimTypes.GivenName, "Sidd"));               

            var manager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();                

            var manager1 = HttpContext.Current.GetOwinContext().Get<ApplicationDbContext>();

            var user = manager.FindByName(name);

            manager.GetRoles(user.Id).ToList().ForEach(
                role => p.Identities.First().AddClaim(new Claim(ClaimTypes.Role, role)));

            return p;
        }
        else
        {
            return Principal.Create("Application",
                new Claim(ClaimTypes.Name, name),
               new Claim(ClaimTypes.GivenName, name));
        }

        //return new ClaimsPrincipal(new ClaimsIdentity(claims, "form"));
    }

現在我的問題是:

1.)如何使用與IdentityServer3連接的OpenID對我的成員數據庫進行驗證

2.)從Winform應用程序或任何其他域或請求頁面重定向回到Default.aspx.cs頁面后,實現SSO或測試SSO

3.)哪些URL值應屬於開放ID的授權

4.)我們需要添加任何證書嗎?

5.)我目前有一個sql server數據庫。 如何重新使用User表和進行身份驗證(如果不通過ASP.NET Identity Manager)。

任何幫助,鏈接或建議都將非常有用。 我在為使此代碼正確而付出很多努力,如果我對代碼邏輯有所了解,那將是一件好事。

提前致謝!!!..

1.)您必須實現IUserService並將其注入IoC。 該實現應深入到用戶存儲中,並確保憑據和有效憑據並在上下文中設置適當的AuthenticateResult。

2.)完成步驟1后,您將在IdSrv上擁有一個會話cookie,該會話cookie將確保與使用同一提供程序的其他客戶端的SSO。

3.)授權是您的IdSrv托管的根uri。 看起來像是它的http:// localhost:52262 / Core ,但請檢查您的IdSrv啟動。

4.)演示中應該提供一個簽名pfx證書,但是您可以(並且最終應該)也可以生成自己的證書。

5.)參見#1

是一個樣板的IUserService實現,但是如上所述,您應該進入數據庫並驗證用戶。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM