【问题标题】:Add a claim to JWT as an array?将 JWT 声明作为数组添加?
【发布时间】:2015-01-31 16:53:00
【问题描述】:

使用 thinktecture JWT 身份验证资源所有者流程,我将 JWT 的声明部分用于客户端消费。 我的问题是,是否可以在身份服务器中添加声明并将其解码为客户端中的数组。

数组类型没有 ClaimTypeValues。

作为一种解决方法:

var user = IdentityServerPrincipal.Create(response.UserName, response.UserName);
                user.Identities.First()
                               .AddClaims(
                                        new List<Claim>()
                                        {
                                            new Claim(ClaimTypes.Name, response.UserName),
                                            new Claim(ClaimTypes.Email, response.Email),
                                            new Claim(FullName, response.FullName),
                                            new Claim(AuthorizedCompanies,JsonConvert.SerializeObject(response.AuthorizedCompanies))
                                        });

return new AuthenticateResult(user);

我将声明添加为 json 数组以声明 AuthorizedCompanies 并在客户端对其进行解析。如果有的话,这里的设计模式是什么?

【问题讨论】:

    标签: c# jwt claims-based-identity thinktecture-ident-server


    【解决方案1】:

    从个人经验来看,当 ValueType 始终为“String”类型时,与索赔商店进行互操作会更容易。虽然当您知道自己正在处理复杂类型时,这似乎与直觉相悖,但它至少易于理解。

    我解决数组需求的方法是让我的应用程序代码期望针对相关声明类型存在多个声明,并保持每个声明值都是简单类型。

    例子:

    var authorizeCompanies = identity.FindAll(AuthorizedCompanies).Select(c => c.Value);
    

    当然,您也可以这样添加它们:

    identity.AddClaim(ClaimTypes.Name, response.UserName);
    identity.AddClaim(AuthorizedCompanies, "CompanyX");
    identity.AddClaim(AuthorizedCompanies, "CompanyY");
    identity.AddClaim(AuthorizedCompanies, "CompanyZ");
    

    IdentityServer 开箱即用地支持此模型。在为此类身份生成令牌时,它会自动将该声明的值作为数组写入。

    {
        "aud": "Identity Server example/resources", 
        "iss": "Identity Server example", 
        "exp": 1417718816, 
        "sub": "1234",
        "scope": ["read", "write"], // <-- HERE
        "foo": ["bar", "baz"],      // <-- HERE TOO!
        "nbf": 1417632416
    }
    

    这种声明方法与假设所有声明都是类型 -> 值的一对一映射相反。

    【讨论】:

    • 如果您只有一个 company,那么您将不会得到一个数组,而是 AuthorizedCompanies 声明中的一个简单字符串。但是如果你有多个,那么你会得到一个字符串数组。这是正确的吗?
    • 我正在考虑做这样的事情,但后来我在 JWT 规范中发现:JWT 声明集中的声明名称必须是唯一的; JWT 解析器必须要么拒绝具有重复声明名称的 JWT,要么使用仅返回词法上最后一个重复成员名称的 JSON 解析器(第 4 节下的tools.ietf.org/html/rfc7519
    • @FercoCQ 我认为 IS 正在返回一个带有 json 编码数组值的声明名称,因此它不违反 rfc 定义。
    • @Vočko 确实...我从 .Net 方面查看问题,但我实际构建 JWT 的代码必须将多个“相同类型”声明转换为数组以遵守与规范。
    • 请注意,JWT OAuth Access token spec 表示范围应该按照 RFC8693 中的描述进行格式化,这是一个空格分隔的列表而不是数组,所以虽然你可以这样做,但你不应该为范围这样做。
    【解决方案2】:

    我遇到了类似的问题,在我的情况下,我声称是数组,但有时根据用户权限只有一项。在这种情况下,如果您使用 new Claim("key", "value") 添加它们,当有单个对象时它们将是字符串,当 > 1 时它们将是数组,这是不可接受的。

    在这种情况下,更好的解决方案是使用 JwtPayload 来构建 JwtSecurityToken 对象。

    var payload = new JwtPayload
        {
            { "ver", version },
            { "iss", "example.com"},
            { "iat", DateTimeOffset.UtcNow.ToUnixTimeSeconds()},
            { "exp", DateTimeOffset.UtcNow.AddHours(1).ToUnixTimeSeconds()},
            { "aud", myExampleStringList }
        };
    var token = new JwtSecurityToken(new JwtHeader(_signingCredentials), payload);
    

    这适用于使用 System.IdentityModel.Tokens.Jwt v3.0 的 .netcore 3.0,但我无法确认其他版本。

    【讨论】:

    • 如果您想控制声明出现的顺序,这也很好
    【解决方案3】:

    使用 JsonClaimValueTypes 作为声明类型

    var tokenDescriptor = new SecurityTokenDescriptor
       {
        Subject = new ClaimsIdentity(new Claim[]
         { new Claim("listName", list != null ? JsonSerializer.Serialize(user.RoleName) : string.Empty,JsonClaimValueTypes.JsonArray)
        }}
    

    【讨论】:

    • 谢谢,这真的解决了我的问题
    【解决方案4】:

    如果您想向数组添加单个值

    Identity Server 会将值从数组转换为字符串。一个更简单的解决方案是将数组转换为 json 并将 valueType 作为 json 添加到声明中。

    IList<string> companies = new List<string>();
    companies.Add("CompanyA");
    string companiesJson = JsonConvert.SerializeObject(companies);
    context.IssuedClaims.Add(new Claim("Companies", companiesJson, IdentityServerConstants.ClaimValueTypes.Json));
    

    上述解决方案将允许您添加一个或多个值以声明为数组。

    【讨论】:

      猜你喜欢
      • 2020-01-18
      • 2016-05-19
      • 2018-07-05
      • 2018-06-02
      • 1970-01-01
      • 2019-02-26
      • 2020-01-27
      • 2019-10-01
      • 2017-05-25
      相关资源
      最近更新 更多