我可以看到我正在期待的数据正在登录时返回,并在Starup.Auth.cs中作为声明添加.但是,当我在帐户控制器内时,唯一出现在UserManager或UserStore中的声明是由LOCAL AUTHORITY发行的.没有找到Facebook(或其他外部提供商)的索赔.索赔附加在哪里上下文? (我在使用VS2013 RTM.)
Azure上的完整来源和实时网站链接:https://github.com/johndpalm/IdentityUserPropertiesSample/tree/VS2013rtm
这是我在Startup.Auth.cs中的内容:
var facebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions() { AppId = ConfigurationManager.AppSettings.Get("FacebookAppId"),AppSecret = ConfigurationManager.AppSettings.Get("FacebookAppSecret"),Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider() { OnAuthenticated = (context) => { const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string"; foreach (var x in context.User) { var claimType = string.Format("urn:facebook:{0}",x.Key); string claimValue = x.Value.ToString(); if (!context.Identity.HasClaim(claimType,claimValue)) context.Identity.AddClaim(new System.Security.Claims.Claim(claimType,claimValue,XmlSchemaString,"Facebook")); } context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token",context.AccessToken,"Facebook")); return Task.FromResult(0); } } }; facebookOptions.Scope.Add("email"); app.UseFacebookAuthentication(facebookOptions);
捕获外部登录属性的另一种方法是为访问令牌添加一个声明,并使用属性填充它:
const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string"; var facebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions { AppId = ConfigurationManager.AppSettings.Get("FacebookAppId"),Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider() { OnAuthenticated = (context) => { var claim = new System.Security.Claims.Claim("urn:facebook:access_token","Facebook"); foreach (var x in context.User) { string key = string.Format("urn:facebook:{0}",x.Key); string value = x.Value.ToString(); claim.Properties.Add(key,value); } context.Identity.AddClaim(claim); return Task.FromResult(0); } } };
注意 – 此示例不起作用:尽管通过属性传递单个声明是很好的.外部cookie似乎注意到声明属性.当从身份获取后,属性为空.
解决方法
这对我有用:
在Startup.ConfigureAuth(StartupAuth.cs)中创建一个新的(在此插入提供者名称)AuthenticationOptions对象,传递客户端ID,客户机密码和新的AuthenticationProvider.您将使用一个lambda表达式来传递OnAuthenticated方法一些代码,以将Claim声明添加到包含从context.Identity中提取的值的标识中.
StartUp.Auth.cs
// Facebook : Create New App // https://dev.twitter.com/apps if (ConfigurationManager.AppSettings.Get("FacebookAppId").Length > 0) { var facebookOptions = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions() { AppId = ConfigurationManager.AppSettings.Get("FacebookAppId"),Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider() { OnAuthenticated = (context) => { context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token","Facebook")); foreach (var x in context.User) { var claimType = string.Format("urn:facebook:{0}",x.Key); string claimValue = x.Value.ToString(); if (!context.Identity.HasClaim(claimType,claimValue)) context.Identity.AddClaim(new System.Security.Claims.Claim(claimType,"Facebook")); } return Task.FromResult(0); } } }; app.UseFacebookAuthentication(facebookOptions); }
注意:Facebook验证提供商使用这里使用的代码.如果您使用与Microsoft帐户提供程序相同的代码(或Foursquare provider我使用MS帐户代码作为模型创建),则无法登录.如果您只选择access_token参数,则可以正常工作.似乎有些参数打破了登录过程. (An issue has been opened on katanaproject.codeplex.com if progress on this is of interest to you.)如果我找到原因,我会更新我没有太多的Twitter或Google,除了验证我可以获得access_token.
var msaccountOptions = new Microsoft.Owin.Security.MicrosoftAccount.MicrosoftAccountAuthenticationOptions() { ClientId = ConfigurationManager.AppSettings.Get("MicrosoftClientId"),ClientSecret = ConfigurationManager.AppSettings.Get("MicrosoftClientSecret"),Provider = new Microsoft.Owin.Security.MicrosoftAccount.MicrosoftAccountAuthenticationProvider() { OnAuthenticated = (context) => { context.Identity.AddClaim(new System.Security.Claims.Claim("urn:microsoftaccount:access_token","Microsoft")); return Task.FromResult(0); } } }; app.UseMicrosoftAccountAuthentication(msaccountOptions);
在AccountController中,我使用外部cookie从AuthenticationManager中提取ClaimsIdentity.然后将其添加到使用应用程序cookie创建的身份.我忽略了以“… schemas.xmlsoap.org/ws/2005/05/identity/claims”开头的任何声明,因为它似乎打破了登录.
AccountController.cs
private async Task SignInAsync(CustomUser user,bool isPersistent) { AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie); var identity = await UserManager.CreateIdentityAsync(user,DefaultAuthenticationTypes.ApplicationCookie); // Extracted the part that has been changed in SignInAsync for clarity. await SetExternalProperties(identity); AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent },identity); } private async Task SetExternalProperties(ClaimsIdentity identity) { // get external claims captured in Startup.ConfigureAuth ClaimsIdentity ext = await AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie); if (ext != null) { var ignoreClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims"; // add external claims to identity foreach (var c in ext.Claims) { if (!c.Type.StartsWith(ignoreClaim)) if (!identity.HasClaim(c.Type,c.Value)) identity.AddClaim(c); } } }
最后,我想显示任何不是从LOCAL AUTHORITY的值.我创建了一个部分视图_ExternalUserPropertiesListPartial,出现在/Account/Manage page.我得到我以前存储的AuthenticationManager.User.Claims的声明,然后将其传递给视图.
AccountController.cs
[ChildActionOnly] public ActionResult ExternalUserPropertiesList() { var extList = GetExternalProperties(); return (ActionResult)PartialView("_ExternalUserPropertiesListPartial",extList); } private List<ExtPropertyviewmodel> GetExternalProperties() { var claimlist = from claims in AuthenticationManager.User.Claims where claims.Issuer != "LOCAL AUTHORITY" select new ExtPropertyviewmodel { Issuer = claims.Issuer,Type = claims.Type,Value = claims.Value }; return claimlist.ToList<ExtPropertyviewmodel>(); }
只是为了彻底,看法:
_ExternalUserPropertiesListPartial.cshtml
@model IEnumerable<MySample.Models.ExtPropertyviewmodel> @if (Model != null) { <legend>External User Properties</legend> <table class="table"> <tbody> @foreach (var claim in Model) { <tr> <td>@claim.Issuer</td> <td>@claim.Type</td> <td>@claim.Value</td> </tr> } </tbody> </table> }
再次,工作示例和完整的代码在GitHub:https://github.com/johndpalm/IdentityUserPropertiesSample上
任何反馈,更正或改进将不胜感激.