C# Asp.Net Core 3标识-来自浏览器的JWT中不存在自定义声明

C# Asp.Net Core 3标识-来自浏览器的JWT中不存在自定义声明,c#,authentication,jwt,asp.net-core-identity,asp.net-core-3.0,C#,Authentication,Jwt,Asp.net Core Identity,Asp.net Core 3.0,Asp.Net核心3.0 我正在使用ASP.NET核心web应用程序和身份验证(个人用户帐户)模板(来自Visual Studio 2019)。 我的目的是在生成的JWT中添加一些自定义声明,并在浏览器中使用它们。 为此,我扩展了UserClaimsPrincipalFactory public class MyCustomClaimsInjector : UserClaimsPrincipalFactory<ApplicationUser> { public MyCusto

Asp.Net核心3.0
我正在使用ASP.NET核心web应用程序和身份验证(个人用户帐户)模板(来自Visual Studio 2019)。
我的目的是在生成的
JWT
中添加一些自定义声明,并在浏览器中使用它们。
为此,我扩展了
UserClaimsPrincipalFactory

public class MyCustomClaimsInjector : UserClaimsPrincipalFactory<ApplicationUser>
{
    public MyCustomClaimsFactory(UserManager<ApplicationUser> userManager, IOptions<IdentityOptions> optionsAccessor) : base(userManager, optionsAccessor)
    {
    }

    protected override async Task<ClaimsIdentity> GenerateClaimsAsync(ApplicationUser user)
    {
        var id = await base.GenerateClaimsAsync(user);
        id.AddClaim(new Claim("my_claim1", "AdditionalClaim1"));
        id.AddClaim(new Claim("my_claim2", "AdditionalClaim2"));
        return id;
    }
}
在从SPA客户端启动的登录阶段,调试器通过
MyCustomClaimsFactory
并将声明添加到
GenerateClaimsAsync
方法中的
ClaimsEntity

但是,我发现奇怪的是,为什么浏览器中收到的JWT不包含由
MyCustomClaimsFactory
添加的声明

我是否希望在JWT浏览器中看到自定义声明

有人能给我建议挖的方向吗。。。为什么JWT中没有这些声明

解码JWT为:

SPA应用程序:
将分享我的结果。希望这能帮助其他人

我已经实现了
IProfileService
并在
ConfigureServices
中管道化了
.AddProfileService()
实现

public class ProfileService : IProfileService
{
    protected UserManager<ApplicationUser> _userManager;

    public ProfileService(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {         
        var user = await _userManager.GetUserAsync(context.Subject);

        var claims = new List<Claim>
        {
            new Claim("my_FirstName", "user_FirstName"),
            new Claim("my_LastName", "user_LastName")
        };

        context.IssuedClaims.AddRange(claims);
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {            
        var user = await _userManager.GetUserAsync(context.Subject);

        context.IsActive = (user != null);
    }
}
public类ProfileService:IProfileService
{
受保护的UserManager\u UserManager;
公共配置文件服务(UserManager UserManager)
{
_userManager=userManager;
}
公共异步任务GetProfileDataAsync(ProfileDataRequestContext上下文)
{         
var user=await\u userManager.GetUserAsync(context.Subject);
var索赔=新列表
{
新索赔(“我的名字”、“用户名字”),
新索赔(“我的姓氏”、“用户姓氏”)
};
context.IssuedClaims.AddRange(索赔);
}
公共异步任务IsActiveAsync(IsActiveContext上下文)
{            
var user=await\u userManager.GetUserAsync(context.Subject);
context.IsActive=(user!=null);
}
}
Startup.cs文件

services.AddIdentityServer()
        .AddApiAuthorization<ApplicationUser, ApplicationDbContext>()
        .AddProfileService<ProfileService>();
services.AddIdentityServer()
.addapi授权()
.AddProfileService();
因此,现在JWT包含了我的自定义声明
我不知道为什么
UserClaimsPrincipalFactory
的覆盖无法解决这个问题。

我将尝试更深入地研究这些领域。

所以今天我遇到了同样的问题。我以前没有使用过IdentityServer,所以我不能完全确定下面的方法是否正确,但这肯定比创建自己的IProfileService实现更容易

默认配置文件服务调用

context.AddRequestedClaims(principal.Claims);
请求的声明在您正在访问的IdentityServer API资源上定义。此资源配置是通过调用

services.AddAuthentication()
        .AddIdentityServerJwt();
这将创建名为“{Environment.ApplicationName}API”的默认ApiResource配置。 此对象还包含生成JWT时要包含的声明类型集合

我找不到任何关于是否也可以在appsettings.json中设置的文档,但是您可以在启动代码中访问它

TLDR;将启动代码更改为类似以下内容:

Startup.cs:

public class Startup
{
    public Startup(IConfiguration configuration, IWebHostEnvironment environment)
    {
        Configuration = configuration;
        Environment = environment;
    }

    public IConfiguration Configuration { get; }
    public IWebHostEnvironment Environment { get; }

    // ...

    public void ConfigureServices(IServiceCollection services)
    {
        // ...

        services.AddIdentityServer()
            .AddApiAuthorization<User, ApplicationDbContext>(options =>
            {
                // The options.ApiResources collection is automatically populated
                // by services.AddAuthentication().AddIdentityServerJwt();
                var apiResource = options.ApiResources[$"{Environment.ApplicationName}API"];
                // Example: add the user's roles to the token
                apiResource.UserClaims.Add(JwtClaimTypes.Role);
                // Example: add another custom claim type
                apiResource.UserClaims.Add("CustomClaimName");
            });

        services.AddAuthentication()
            .AddIdentityServerJwt();

        // ...
    }
}
公共类启动
{
公共启动(IConfiguration配置、IWebHostEnvironment环境)
{
配置=配置;
环境=环境;
}
公共IConfiguration配置{get;}
公共IWebHostEnvironment环境{get;}
// ...
public void配置服务(IServiceCollection服务)
{
// ...
services.AddIdentityServer()
.addapi授权(选项=>
{
//options.ApiResources集合将自动填充
//通过services.AddAuthentication().AddIdentityServerJwt();
var apirource=options.apirources[$“{Environment.ApplicationName}API”];
//示例:将用户的角色添加到令牌
apiResource.UserClaims.Add(JwtClaimTypes.Role);
//示例:添加另一个自定义索赔类型
apiResource.UserClaims.Add(“CustomClaimName”);
});
services.AddAuthentication()
.AddIdentityServerJwt();
// ...
}
}

您是否继续调查为什么使用UserClaimsPrincipalFactory设置索赔不起作用?我今天遇到了同样的问题。开始在gitter asp频道聊天,但没有捕捉到有用的内容。文档太原始了,我考虑等几个月,hopin的小版本也会添加更多细节。我计划在发现真正原因后更新答案。你能给我们举一个你添加的不同索赔类型的例子吗?抱歉,我不太明白ApiResource对象的位置?我在代码中添加了注释和一个使用真实声明类型的示例,希望这能让代码更清晰。ApiResource是自动创建的“options.ApiResources”集合中的配置对象。您可以在文档中了解更多信息:似乎我在创建默认ApiResource配置的位置上出错了;我更新了代码,希望信息现在是正确的。
public class Startup
{
    public Startup(IConfiguration configuration, IWebHostEnvironment environment)
    {
        Configuration = configuration;
        Environment = environment;
    }

    public IConfiguration Configuration { get; }
    public IWebHostEnvironment Environment { get; }

    // ...

    public void ConfigureServices(IServiceCollection services)
    {
        // ...

        services.AddIdentityServer()
            .AddApiAuthorization<User, ApplicationDbContext>(options =>
            {
                // The options.ApiResources collection is automatically populated
                // by services.AddAuthentication().AddIdentityServerJwt();
                var apiResource = options.ApiResources[$"{Environment.ApplicationName}API"];
                // Example: add the user's roles to the token
                apiResource.UserClaims.Add(JwtClaimTypes.Role);
                // Example: add another custom claim type
                apiResource.UserClaims.Add("CustomClaimName");
            });

        services.AddAuthentication()
            .AddIdentityServerJwt();

        // ...
    }
}