[英]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.