本文介绍了如何访问Microsoft.Owin.Security.xyz OnAuthenticated上下文AddClaims值?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试检索作为OnAuthenticated上下文返回的用户属性,并作为声明添加了以下示例:


$ b $我可以看到,我正在期待的数据正在登录时返回,并在Starup.Auth.cs中作为索赔添加。但是,当我在帐户控制器内时,唯一出现在UserManager或UserStore中的声明是由LOCAL AUTHORITY发行的。没有找到Facebook(或其他外部提供商)的索赔。索赔附加在哪里上下文? (我正在使用VS2013 RTM。)



Azure上的完整的源和实时站点链接到这里:



这是我的在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,XmlSchemaString,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),
AppSecret = ConfigurationManager.AppSettings.Get (FacebookAppSecret),
Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider()
{
OnAuthenticated =(context)=>
{
var claim = new System.Security.Claims.Claim(urn:facebook:access_token,context.AccessToken,XmlSchemaString,Facebook);
foreach(上下文中的var x)
{
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似乎注意到声明属性。

解决方案

我能够创建一个工作示例,使用MVC 5 RTM模板,OWIN和ASP.NET标识位。您可以在这里找到完整的来源和实际工作示例的链接:



这对我有用:



在Startup.ConfigureAuth中创建一个新的(在此插入提供者名称)AuthenticationOptions对象(StartupAuth.cs),传递客户端id,客户机密码和新的AuthenticationProvider。你将使用一个lambda表达式来传递OnAuthenticated方法一些代码来添加声明到包含你从context.Identity中提取的值的标识。



StartUp.Auth.cs

  // Facebook:创建新应用
// 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),
AppSecret = ConfigurationManager.AppSettings.Get(FacebookAppSecret),
Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider( )
{
OnAuthenticated =(context)=>
{
context.Identity.AddClaim(new System.Security.Claims.Claim(urn:facebook:access_token,context.AccessToken,XmlSchemaString,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,claimValue,XmlSchemaString,Facebook));

}
返回Task.FromResult(0);
}
}

};
app.UseFacebookAuthentication(facebookOptions);
}

注意:Facebook验证提供商使用此处使用的代码。如果您使用Microsoft帐户提供商(或使用相同的代码,我使用MS帐户代码创建作为模型),它无法登录。如果您只选择access_token参数,则可以正常工作。似乎有些参数打破了登录过程。 (,出现在。我收到以前从AuthenticationManager.User.Claims存储的索赔,然后将其传递给该视图。



AccountController.cs

  [ChildActionOnly] 
public ActionResult ExternalUserPropertiesList()
{
var extList = GetExternalProperties();
return(ActionResult)PartialView(_ ExternalUserPropertiesListPartial,extList);
}

私人列表&ExtPropertyViewModel> GetExternalProperties()
{
var claimlist = from AuthenticationManager.User.Claims
where claims.Issuer!=LOCAL AUTHORITY
选择新的ExtPropertyViewModel
{
发行人= claim.Issuer,
Type = claims.Type,
Value = claims.Value
};

return claimlist.ToList&ExtPropertyViewModel>();
}

只是为了彻底,视图:



_ExternalUserPropertiesListPartial.cshtml

  @model IEnumerable< MySample.Models.ExtPropertyViewModel> 

@if(Model!= null)
{
< legend>外部用户属性< / legend>
< table class =table>
< tbody>
@foreach(Model中的var claim)
{
< tr>
< td> @ claim.Issuer< / td>
< td> @ claim.Type< / td>
< td> @ claim.Value< / td>
< / tr>
}
< / tbody>
< / table>
}

再次,工作示例和完整的代码在GitHub上:



任何反馈,更正,或者改进将不胜感激。


I'm trying to retrieve user properties that are returned as the OnAuthenticated context and added as a claims following this example: How to access Facebook private information by using ASP.NET Identity (OWIN)?

I can see that data I am expecting is being returned at login and is being added as a Claim within Starup.Auth.cs. But, when I am within the Account Controller, the only claims that appears within the UserManager or UserStore is issued by LOCAL AUTHORITY. No claims can be found for Facebook (or other external providers). Where do the claims added to context end up? (I'm using VS2013 RTM.)

Full source and live site on Azure linked here: https://github.com/johndpalm/IdentityUserPropertiesSample/tree/VS2013rtm

Here is what I have in 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, XmlSchemaString, "Facebook"));
                return Task.FromResult(0);
            }
    }

};

facebookOptions.Scope.Add("email");

app.UseFacebookAuthentication(facebookOptions);

An alternative way to capture the external login properties would be to add a single claim for the access token and populate it with properties:

const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";
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) =>
        {
            var claim = new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, XmlSchemaString, "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);
        }
    }
};

NOTE - This sample does not work: Though it would be nice to pass a single claim with properties. The external cookie seems to note honor the claims properties. The properties are empty when retrieving them later from the identity.

解决方案

I was able to create a working example, using MVC 5 RTM templates, OWIN, and ASP.NET Identity bits. You can find the complete source and a link to a live working example here: https://github.com/johndpalm/IdentityUserPropertiesSample

Here's what worked for me:

Create a new (insert provider name here) AuthenticationOptions object in Startup.ConfigureAuth (StartupAuth.cs), passing it the client id, client secret, and a new AuthenticationProvider. You will use a lambda expression to pass the OnAuthenticated method some code to add Claims to the identity which contain the values you extract from 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"),
        AppSecret = ConfigurationManager.AppSettings.Get("FacebookAppSecret"),
        Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider()
        {
            OnAuthenticated = (context) =>
                {
                    context.Identity.AddClaim(new System.Security.Claims.Claim("urn:facebook:access_token", context.AccessToken, XmlSchemaString, "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, claimValue, XmlSchemaString, "Facebook"));

                    }
                    return Task.FromResult(0);
                }
        }

    };
    app.UseFacebookAuthentication(facebookOptions);
}

NOTE: The Facebook auth provider works with the code used here. If you use this same code with the Microsoft Account provider (or Foursquare provider I created using the MS account code as a model), it fails to login. If you select just the access_token parameter, it works fine. Seems like some parameters break the login process. (An issue has been opened on katanaproject.codeplex.com if progress on this is of interest to you.) I'll update if I find the cause. I didn't do much with Twitter or Google beyond verifying that I could get the 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", context.AccessToken, XmlSchemaString, "Microsoft"));
                return Task.FromResult(0);
            }
    }                   
};

app.UseMicrosoftAccountAuthentication(msaccountOptions);

In AccountController, I extract the ClaimsIdentity from the AuthenticationManager using the external cookie. I then add it to the identity created using the application cookie. I ignored any claims that starts with "...schemas.xmlsoap.org/ws/2005/05/identity/claims" since it seemed to break the login.

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

And finally, I want to display whatever values are not from the LOCAL AUTHORITY. I created a partial view _ExternalUserPropertiesListPartial that appears on the /Account/Manage page. I get the claims I previously stored from AuthenticationManager.User.Claims and then pass it to the view.

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

And just to be thorough, the view:

_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>
}

Again, the working example and complete code is on GitHub: https://github.com/johndpalm/IdentityUserPropertiesSample

And any feedback, corrections, or improvements would be appreciated.

这篇关于如何访问Microsoft.Owin.Security.xyz OnAuthenticated上下文AddClaims值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-21 02:52