将JWT声明添加为数组?

ser*_*can 14 claims-based-identity jwt thinktecture-ident-server

使用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);
Run Code Online (Sandbox Code Playgroud)

我将声明添加为json数组来声明AuthorizedCompanies并在客户端解析它.如果有的话,这里的设计模式是什么?

Cre*_*esh 22

从个人经验来看,当ValueType始终为"String"类型时,与声明商店交互更容易.虽然当你知道你正在处理一个复杂的类型时,它可能看起来很直观,但它至少很容易理解.

我接近数组需求的方法是让我的应用程序代码期望对所讨论的声明类型提出多个声明,并保持每个声明值的简单类型.

Examp:

var authorizeCompanies = identity.FindAll(AuthorizedCompanies).Select(c => c.Value);
Run Code Online (Sandbox Code Playgroud)

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

identity.AddClaim(ClaimTypes.Name, response.UserName);
identity.AddClaim(AuthorizedCompanies, "CompanyX");
identity.AddClaim(AuthorizedCompanies, "CompanyY");
identity.AddClaim(AuthorizedCompanies, "CompanyZ");
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

这种声明方法与假设所有声明都是类型 - >值的一对一映射形成对比.

  • 如果您只有一个*公司*,那么您将不会得到一个数组,而是 *AuthorizedCompanies* 声明中的一个简单字符串。但如果有多个,那么您会得到一个字符串数组。它是否正确? (2认同)

小智 17

使用 JsonClaimValueTypes 作为声明类型

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


小智 5

我遇到了类似的问题,在我的情况下,我声称是数组,但有时根据用户权限只有一项。在这种情况下,如果您使用 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);
Run Code Online (Sandbox Code Playgroud)

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