7

从 Visual Studio 的“Web API”项目模板开始,我尝试向/Api/Account/ExternalLogin端点创建的令牌添加自定义声明。我通过回调添加这些FacebookAuthenticationProvider.OnAuthenticated,但它们不会持续到OAuthAuthorizationServerProvider.AuthorizationEndpointResponse().

注意:我正在使用 Rahul Nath 在他的文章ASP.NET Web API 和外部登录 - 使用社交网络进行身份验证 中记录的类似方法

代码

在我Startup.Auth.cs的类的ConfigureAuth()方法(从OwinStartup类的Configuration()方法中调用)中,我向属性添加了一个回调函数OnAuthenticated,以便设置单个声明,foo其值为bar

var facebookAuthenticationProvider = new FacebookAuthenticationProvider() 
{
    OnAuthenticated = (context) => 
    {
        context.Identity.AddClaim(new Claim("foo", "bar"));
        return Task.FromResult(0);
    }
};

然后我将FacebookAuthenticationProvider实例添加到一个新FacebookAuthenticationOptions对象:

var facebookAuthenticationOptions = new FacebookAuthenticationOptions() 
{
    AppId = "XXXX",
    AppSecret = "YYYY",
    Provider = facebookAuthenticationProvider
};

并将其传递给 OWIN 的UseFacebookAuthentication()方法:

app.UseFacebookAuthentication(facebookAuthenticationOptions);

结果

如果我在回调中放置一个断点,OnAuthenticated我可以看到正在添加我的自定义声明,以及许多其他声明(包括来自urn:facebook命名空间的几个声明)。到目前为止,一切都很好。

AuthorizationEndpointResponse()但是,当我在 Facebook 身份验证后通过我的类的方法检查我的声明时,集合OAuthAuthorizationServerProvider中只有两个可用的声明:context.Identity.Claims

所有urn:facebook声明都已删除,我的自定义foo声明也是如此。我假设管道中的其他位置正在使用一组准系统声明重新创建身份,但我不确定在哪里。

想法?

4

2 回答 2

0

我有以下用于访问自定义声明的代码:

 public class AppUser : ClaimsPrincipal{
    public AppUser(ClaimsPrincipal principal): base(principal){}
    public string Role{
        get{
            return this.FindFirst(ClaimTypes.Role).Value;
        }
    }  

    public string ProfileID{
        get{
            return this.FindFirst("ProfileID").Value;
        }
    }
}
于 2015-09-06T08:10:07.103 回答
0

您可能需要编辑 ExternalLoginData 私有类以包含您希望通过流传递的其他声明。在默认的 VS2013 模板类文件中,这个私有类可以在 AccountController.cs 文件中找到。

我遇到了类似的问题,无法从 Google 声明中传递电子邮件,这解决了问题(注意添加的“电子邮件”变量和两种方法中对它的引用:

private class ExternalLoginData
{
    public string LoginProvider { get; set; }
    public string ProviderKey { get; set; }
    public string UserName { get; set; }
    public string Email { get; set; }

    public IList<Claim> GetClaims()
    {
        IList<Claim> claims = new List<Claim>();
        claims.Add(new Claim(ClaimTypes.NameIdentifier, ProviderKey, null, LoginProvider));

        if (UserName != null)
        {
            claims.Add(new Claim(ClaimTypes.Name, UserName, null, LoginProvider));
        }

        if (Email != null)
        {
            claims.Add(new Claim(ClaimTypes.Email, Email, null, LoginProvider));
        }

        return claims;
    }

    public static ExternalLoginData FromIdentity(ClaimsIdentity identity)
    {
        if (identity == null)
        {
            return null;
        }

        Claim providerKeyClaim = identity.FindFirst(ClaimTypes.NameIdentifier);

        if (providerKeyClaim == null || String.IsNullOrEmpty(providerKeyClaim.Issuer)
            || String.IsNullOrEmpty(providerKeyClaim.Value))
        {
            return null;
        }

        if (providerKeyClaim.Issuer == ClaimsIdentity.DefaultIssuer)
        {
            return null;
        }

        return new ExternalLoginData
        {
            LoginProvider = providerKeyClaim.Issuer,
            ProviderKey = providerKeyClaim.Value,
            UserName = identity.FindFirstValue(ClaimTypes.Name),
            Email = identity.FindFirstValue(ClaimTypes.Email)
        };
    }
}
于 2015-11-04T01:12:45.373 回答