如何在 Web API 授权服务中将声明包含在我的 AuthTicket 中?

How do I get claims included in my AuthTicket in a Web API Auth Service?

我有一个带有身份验证服务的 Web API,对于 WPF 客户端,设置如下:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
        ...
    }
}

public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        ...
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId),
            ApplicationCanDisplayErrors = true,
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AllowInsecureHttp = true, // TODO Make false to deploy
        };
        app.UseOAuthAuthorizationServer(OAuthOptions);
    }
}

到目前为止,我只使用过 /Token 端点,因为它至少会授予我不记名令牌。我在身份验证成功时收到的票有签发日期和到期日期、不记名令牌和我的用户名。

如何获得用户的声明(可能还有角色)?有什么我可以在这里做的事情,或者我在验证后通过 API 缓慢地请求它们,并将它们和 Auth Ticket 聚合在 WPF 客户端的 Principal 对象中?

我是否可以在 WPF 应用程序中包含一些身份组件以帮助从令牌中提取声明,以及关于我应该如何执行此操作的任何建议?

我认为让客户端解密令牌是相当危险的。如果他们能做到这一点,恶意行为者就可以修改令牌和其中的声明。如果您不检查声明的有效性(可能是因为它们是由第三方提供的),那么这可能会导致特权升级和您的应用程序受到损害。

如果客户端应用程序需要声明 - 也许是 UI 布局,那么您可以将它们单独提供给令牌。一种方法是通过 ActionFilterAttribute 将声明写入自定义 http header。如果声明在这里被篡改,它只会影响客户端,因为您将在处理任何请求之前检查令牌中的安全声明。

public AddClaimsAttribute : System.Web.Http.Filters.ActionFilterAttribute
{
     var principal = actionExecutedContext.ActionContext.RequestContext.Principal as ClaimsPrincipal;

    if (principal != null)
    {
        var claims = principal.Claims.Select(x => x.Type + ":" + x.Value).ToList();

        actionExecutedContext.Response.Content.Headers.Add("Claims",
           String.Join(",", claims));
    }

}

然后您的客户端只需要检查这个 header 并解析它。

这是一个基本示例,您可以将其格式化为 JSON 或添加一系列自定义 headers "IsAdmin"、"IsEditingUser" 等

因为它是一个过滤器,所以您可以将其全局应用于每个请求、控制器上的每个操作或您需要的特定操作。

您可以通过在令牌响应中添加用户角色轻松实现此目的。为此,您必须在 ApplicationOAuthProvider.cs class 中更新方法 CreateProperties

     public static AuthenticationProperties CreateProperties(User user)
            {
//get only roles ids
//to do: retrieve user roles names 
                var roles = string.Join(",", user.Roles.Select(t => t.RoleId).ToArray());
//expose phone in response
                var phone = user.PhoneNumber;
                IDictionary<string, string> data = new Dictionary<string, string>
                {
                    { "userName", user.UserName },
                    { "userId", user.Id },
                    { "roles", roles},
                    { "phone", phone}
                };
                return new AuthenticationProperties(data);
            }

您可以在邮递员响应中看到 3 个新属性:userId、roles 和 phone。添加新属性时请注意空值。