如何访问 Microsoft.Owin.Security.xyz OnAuthenticated 上下文 AddClaims 值? [英] How do I access Microsoft.Owin.Security.xyz OnAuthenticated context AddClaims values?

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

问题描述

我正在尝试检索作为 OnAuthenticated 上下文返回的用户属性,并按照以下示例添加为声明:如何使用 ASP.NET Identity (OWIN) 访问 Facebook 私人信息?

我可以看到我期望的数据在登录时被返回并被添加为 Starup.Auth.cs 中的声明.但是,当我在 Account Controller 中时,出现在 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 = (上下文) =>{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"));返回 Task.FromResult(0);}}};facebookOptions.Scope.Add("email");app.UseFacebookAuthentication(facebookOptions);

捕获外部登录属性的另一种方法是为访问令牌添加一个声明并用属性填充它:

const string XmlSchemaString = "http://www.w3.org/2001/XMLSchema#string";var facebookOptions = 新 Microsoft.Owin.Security.Facebook.FacebookAuthenticationOptions{AppId = ConfigurationManager.AppSettings.Get("FacebookAppId"),AppSecret = ConfigurationManager.AppSettings.Get("FacebookAppSecret"),Provider = new Microsoft.Owin.Security.Facebook.FacebookAuthenticationProvider(){OnAuthenticated = (上下文) =>{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);字符串值 = x.Value.ToString();claim.Properties.Add(key, value);}context.Identity.AddClaim(claim);返回 Task.FromResult(0);}}};

注意 - 此示例不起作用:尽管传递带有属性的单个声明会很好.外部 cookie 似乎注意到尊重声明属性.稍后从身份中检索属性时,这些属性为空.

解决方案

我能够使用 MVC 5 RTM 模板、OWIN 和 ASP.NET Identity 位创建一个工作示例.您可以在此处找到完整的源代码和实时工作示例的链接:https://github.com/johndpalm/IdentityUserPropertiesSample

这对我有用:

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

StartUp.Auth.cs

//Facebook : 创建新应用//https://dev.twitter.com/appsif (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.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 帐户提供程序(或 Foursquare 提供程序)使用相同的代码,我使用 MS 帐户代码创建作为模型),它无法登录.如果您只选择 access_token 参数,它工作正常.似乎某些参数会破坏登录过程.(如果您对这方面的进展感兴趣,已经在 katanaproject.codeplex.com 上打开了一个问题.)我会如果我找到原因更新.除了验证我是否可以获得 access_token 之外,我没有用 Twitter 或 Google 做太多事情.

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.Identity.AddClaim(new System.Security.Claims.Claim("urn:microsoftaccount:access_token", context.AccessToken, XmlSchemaString, "Microsoft"));返回 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);//为清楚起见,提取了 SignInAsync 中已更改的部分.等待 SetExternalProperties(identity);AuthenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, 身份);}私有异步任务 SetExternalProperties(ClaimsIdentity 身份){//获取在 Startup.ConfigureAuth 中捕获的外部声明ClaimsIdentity ext = 等待 AuthenticationManager.GetExternalIdentityAsync(DefaultAuthenticationTypes.ExternalCookie);如果(分机!= null){var ignoreClaim = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims";//向身份添加外部声明foreach (var c in ext.Claims){if (!c.Type.StartsWith(ignoreClaim))if (!identity.HasClaim(c.Type, c.Value))身份.AddClaim(c);}}}

最后,我想显示不是来自 LOCAL AUTHORITY 的任何值.我创建了一个局部视图 _ExternalUserPropertiesListPartial 出现在 /Account/Manage 页面.我从 AuthenticationManager.User.Claims 获取我之前存储的声明,然后将其传递给视图.

AccountController.cs

[ChildActionOnly]公共 ActionResult ExternalUserPropertiesList(){var extList = GetExternalProperties();return (ActionResult)PartialView("_ExternalUserPropertiesListPartial", extList);}私有列表获取外部属性(){var claimlist = 来自 AuthenticationManager.User.Claims 中的声明其中 claim.Issuer != "LOCAL AUTHORITY"选择新的 ExtPropertyViewModel{发行人 = 索赔.发行人,类型 = 声明.类型,价值 = 索赔.价值};return claimlist.ToList();}

为了彻底,观点:

_ExternalUserPropertiesListPartial.cshtml

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

同样,工作示例和完整代码位于 GitHub 上:https://github.com/johndpalm/IdentityUserPropertiesSample

如有任何反馈、更正或改进,我们将不胜感激.

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 值?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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