代码之家  ›  专栏  ›  技术社区  ›  developer82

IdentityServer4声明不是混合流令牌的一部分

  •  0
  • developer82  · 技术社区  · 6 年前

    QuickStart UI

    在我的 AccountController 用户成功通过身份验证后,我有以下代码让他登录:

    await HttpContext.SignInAsync("anon@nymous.com", "anon@nymous.com", null, new Claim("MyName", "Ophir"));
    

    在导致此流的MVC网站中,在我要“保护”的页面上,我有以下代码:

    [Authorize]
    public IActionResult RestrictedMvcResource()
    {
           var token = _httpContext.HttpContext.GetTokenAsync("access_token").Result;
           var identity = User.Identity;
           return View();
    }
    

    成功登录后,调试器会很好地处理这段代码,我将获得访问令牌。

    https://jwt.io/ )我看到了名字和主题,但我没有看到 MyName 声称我已经定义了。

    (我的系统中还有一个 client_credentials 它确实返回令牌上的声明(但它使用不同的代码流)。

    如何返回混合流令牌上的声明?

    编辑:

    1. 实施 IProfileService 如(选定的)答案所建议的。以下是我的实现:
    public class ProfileService : IProfileService
    {
        public Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            context.AddRequestedClaims(context.Subject.Claims);
    
            foreach (Claim claim in context.Subject.Claims)
            {
                if (context.IssuedClaims.Contains(claim))
                    continue;
    
                context.IssuedClaims.Add(claim);
            }
    
            return Task.FromResult(0);
        }
    
        public Task IsActiveAsync(IsActiveContext context)
        {
            context.IsActive = true;
            return Task.FromResult(0);
        }
    }
    

    这将添加令牌上尚未存在的任何声明。

    1. HttpContext.SignInAsync 您必须通过索赔清单,否则将不会有其他索赔 context.Subject.Claims 收藏。
    0 回复  |  直到 6 年前
        1
  •  4
  •   Vidmantas Blazevicius    6 年前

    您可以实现自定义 IProfileService 如果要向令牌添加自定义声明。

    您可以在中找到更多信息 Identity Server 4 docs

    简单的自定义配置文件服务示例如下:

    public class CustomProfileService : IProfileService
    {
        public Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            context.AddRequestedClaims(context.Subject.Claims);
            context.IssuedClaims.Add(new Claim("MyName", "Ophir"));
            return Task.FromResult(0);
        }
    
        public Task IsActiveAsync(IsActiveContext context)
        {
            context.IsActive = true;    
            return Task.FromResult(0);
        }
    }
    

    一旦你有了这个,只要注册到DI:

    services.AddTransient<IProfileService, CustomProfileService>();
    

    access_token id_token context.Caller 根据鲁德的意见,如果你只想在某些类型的代币额外索赔。

    编辑: 另外,您也可以将声明直接添加到用户配置中,如 Identity Server 4 quickstarts :

                new TestUser
                {
                    SubjectId = "1",
                    Username = "alice",
                    Password = "password",
    
                    Claims = new []
                    {
                        new Claim("MyName", "Ophir")
                    }
                },
    

    如果你最终没有实现自定义 IP文件服务 继续使用 DefaultProfileService ,则还需要添加自定义 IdentityResource

    return new List<IdentityResource>
    {
        //..Your other configured identity resources
    
        new IdentityResource(
        name: "custom.name",
        displayName: "Custom Name",
        claimTypes: new[] { "MyName" });
    };
    

    任何想要在令牌中添加此声明的客户端都需要请求 custom.name 范围。

        2
  •  0
  •   rleffler    6 年前

    AspNet.Security.OpenIdConnect.Server不会序列化未设置目标的声明。我在使用OpenIdDict时遇到了这个问题。

    试试这个:

    var claim = new Claim("MyName", "Ophir");
    claim.SetDestinations(OpenIdConnectConstants.Destinations.AccessToken);
    
    await HttpContext.SignInAsync("anon@nymous.com", "anon@nymous.com", null, claim);
    

    您可能需要添加以下名称空间:

    using AspNet.Security.OpenIdConnect.Extensions;
    using AspNet.Security.OpenIdConnect.Primitives;
    
        3
  •  0
  •   Schwarzie2478    6 年前

    我通过两个步骤为identityserver的令牌添加声明。

    通过一个定制的配置文件服务(如其他答案中的一个),您可以为用户定义自己的声明。

    然后可以通过userinfo端点请求这些声明。

    或者创建一个Api(资源),例如includeNameAccessToken,如果您请求将该Api作为作用域,则该Api默认情况下会将名称声明添加到访问令牌中。