简体   繁体   English

如何在API请求中提供自定义用户声明

[英]How to make custom user claims be available in API requests

I have a solution consisting of: 我有一个解决方案包括:

  • ASP.NET Core 2.1 running IdentityServer4 on top of ASP.NET Identity Core. ASP.NET Core 2.1在ASP.NET Identity Core之上运行IdentityServer4。
  • ASP.NET Core 2.1 Web API set to use the IdentityServer as the authentication provider. ASP.NET Core 2.1 Web API设置为使用IdentityServer作为身份验证提供程序。
  • A React SPA web application using oidc-client javascript library. 使用oidc-client javascript库的React SPA Web应用程序。

When I create new users I set some custom claims that are saved in the AspNetUserClaims table which looks like this: 当我创建新用户时,我设置了一些保存在AspNetUserClaims表中的自定义声明,如下所示: 在此输入图像描述

Then, on my API project, inside a controller I want to get those user claims of the authenticated user. 然后,在我的API项目中,在控制器内部,我希望获得经过身份验证的用户的那些用户声明。
I was expecting this.User.Claims to get me those, but instead that's returning the following, which seem to be claims related to the client app, not the user. 我期待着这个this.User.Claims让我这些,但相反,它返回以下,这似乎是与客户端应用程序相关的声明,而不是用户。

在此输入图像描述

How can I access those custom user claims ( address, location, tenant_role ) from a controller inside the Web API project? 如何从Web API项目中的控制器访问这些自定义用户声明( address, location, tenant_role )?
Bare in mind that the API project doesn't have access to the UserManager class or anything ASP.NET Identity Core related. 请记住,API项目无权访问UserManager类或与ASP.NET Identity Core相关的任何内容。

So, I order for my custom user claim to be available in every API request I had to do the following when setting up the ApiResource on the IdentityServer startup. 所以,我命令我的自定义用户声明在每个API请求中都可用,我在IdentityServer启动时设置ApiResource时必须执行以下操作。

//Config.cs
public static IEnumerable<ApiResource> GetApiResources()
{
    ApiResource apiResource = new ApiResource("api1", "DG Analytics Portal API")
    {
        UserClaims =
        {
            JwtClaimTypes.Name,
            JwtClaimTypes.Email,
            AnalyticsConstants.TenantRoleClaim // my custom claim key/name
        }
    };

    return new List<ApiResource>
    {
        apiResource
    };
}

This method is passed to the services.AddInMemoryApiResources (or whatever storage method you're using) 此方法传递给services.AddInMemoryApiResources (或您正在使用的任何存储方法)

IIdentityServerBuilder builder = services
                .AddIdentityServer(options =>
                {
                    options.Events.RaiseErrorEvents = true;
                    options.Events.RaiseInformationEvents = true;
                    options.Events.RaiseFailureEvents = true;
                    options.Events.RaiseSuccessEvents = true;
                })
                .AddInMemoryIdentityResources(Config.GetIdentityResources())
                .AddInMemoryApiResources(Config.GetApiResources()) // here
                .AddInMemoryClients(Config.GetClients())
                .AddAspNetIdentity<ApplicationUser>();

With that setup, whenever an API endpoint is hit, my custom TenantRole claim is present so I can simply do User.FindFirst(AnalyticsConstants.TenantRoleClaim) to get it. 通过该设置,无论何时命中API端点,我的自定义TenantRole声明都存在,因此我可以简单地执行User.FindFirst(AnalyticsConstants.TenantRoleClaim)来获取它。

You'll need to define identity resources and scopes a la: 你需要定义身份资源和范围a:

http://docs.identityserver.io/en/latest/topics/resources.html http://docs.identityserver.io/en/latest/topics/resources.html

And then ensure that they are exposed by your IProfileService or IClaimsService implementation in your identity server: 然后确保它们由身份服务器中的IProfileService或IClaimsService实现公开:

http://docs.identityserver.io/en/latest/reference/profileservice.html http://docs.identityserver.io/en/latest/reference/profileservice.html

They claims can either be included in the tokens themselves or be access via the user info endpoint as needed - this is sensible if your claim data is particularly large (ie in the 1000s of characters). 它们声称可以包含在令牌中,也可以根据需要通过用户信息端点进行访问 - 如果您的声明数据特别大(即1000个字符),这是明智的。

You can use ClaimsPrincipal.FindFirst() to access your customized claims. 您可以使用ClaimsPrincipal.FindFirst()来访问您的自定义声明。

Doc: https://docs.microsoft.com/en-us/dotnet/api/system.security.claims.claimsprincipal.findfirst?view=netcore-2.1 Doc: https//docs.microsoft.com/en-us/dotnet/api/system.security.claims.claimsprincipal.findfirst? view = netcore- 2.1

Example: User.FindFirst("your_claim_key").Value 示例: User.FindFirst("your_claim_key").Value

I wrote this extender for use in MVC 5 but since it uses the http context and system security (and not the User Manager or Identity) I assume the internals of this will work on MVC6 我编写了这个扩展程序用于MVC 5,但由于它使用了http上下文和系统安全性(而不是用户管理器或身份),我认为这种内部结构适用于MVC6

public static bool UserHasSpecificClaim(this HtmlHelper h, string claimType, string claimValue)
{
    // get user claims
    var user = HttpContext.Current.User as System.Security.Claims.ClaimsPrincipal;

    if (user != null)
    {
        // Get the specific claim if any
        return user.Claims.Any(c => c.Type == claimType && c.Value == claimValue);
    }

    return false;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM