Skip to content

Commit 97888a2

Browse files
author
Brent Schmaltz
committed
Merged PR 10258: Compatibility with 6x for bool claims (#2367)
Compatibility with 6x for bool claims (#2367) * Compatibility with 6x for bool claims Fix behavior where ToString is used on bool values resulting in the value being True/False instead of true/false * Use direct ClaimValueType --------- Co-authored-by: Keegan Caruso <[email protected]> ---- #### AI-Generated Description The pull request modifies the handling of boolean claims in the JsonWebToken library. It changes the encoding and decoding of boolean values to use lowercase "true" and "false" instead of uppercase "True" and "False". It also adds unit tests to verify the expected behavior. The main changes are in the following files: - **JsonWebTokenTests.cs**: Adds a new test method `BoolClaimsEncodedAsExpected` to check the encoding and decoding of boolean claims. - **JwtPayload.cs**: Adds logic to handle boolean values in the `CreateClaims` and `CreateClaimFromObject` methods. - **JsonClaimSet.cs**: Adds logic to handle boolean values in the `CreateClaimFromObject` and `CreateClaimFromJsonElement` methods.
1 parent 5c1ea4a commit 97888a2

File tree

5 files changed

+82
-8
lines changed

5 files changed

+82
-8
lines changed

src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,13 @@ internal static void CreateClaimFromObject(List<Claim> claims, string claimType,
6161
else if (value is long l)
6262
claims.Add(new Claim(claimType, l.ToString(CultureInfo.InvariantCulture), ClaimValueTypes.Integer64, issuer, issuer));
6363
else if (value is bool b)
64-
claims.Add(new Claim(claimType, b.ToString(CultureInfo.InvariantCulture), ClaimValueTypes.Boolean, issuer, issuer));
64+
{
65+
// Can't just use ToString or bools will get encoded as True/False instead of true/false.
66+
if (b)
67+
claims.Add(new Claim(claimType, "true", ClaimValueTypes.Boolean, issuer, issuer));
68+
else
69+
claims.Add(new Claim(claimType, "false", ClaimValueTypes.Boolean, issuer, issuer));
70+
}
6571
else if (value is double d)
6672
claims.Add(new Claim(claimType, d.ToString(CultureInfo.InvariantCulture), ClaimValueTypes.Double, issuer, issuer));
6773
else if (value is DateTime dt)
@@ -108,9 +114,9 @@ internal static Claim CreateClaimFromJsonElement(string claimType, string issuer
108114
else if (jsonElement.ValueKind == JsonValueKind.Object)
109115
return new Claim(claimType, jsonElement.ToString(), JsonClaimValueTypes.Json, issuer, issuer);
110116
else if (jsonElement.ValueKind == JsonValueKind.False)
111-
return new Claim(claimType, "False", ClaimValueTypes.Boolean, issuer, issuer);
117+
return new Claim(claimType, "false", ClaimValueTypes.Boolean, issuer, issuer);
112118
else if (jsonElement.ValueKind == JsonValueKind.True)
113-
return new Claim(claimType, "True", ClaimValueTypes.Boolean, issuer, issuer);
119+
return new Claim(claimType, "true", ClaimValueTypes.Boolean, issuer, issuer);
114120
else if (jsonElement.ValueKind == JsonValueKind.Number)
115121
{
116122
if (jsonElement.TryGetInt32(out int i))

src/System.IdentityModel.Tokens.Jwt/JwtPayload.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,14 @@ public virtual IEnumerable<Claim> Claims
543543
}
544544
else if (keyValuePair.Value is DateTime dateTime)
545545
claims.Add(new Claim(keyValuePair.Key, dateTime.ToString("o", CultureInfo.InvariantCulture), ClaimValueTypes.DateTime, issuer, issuer));
546+
else if (keyValuePair.Value is bool boolValue)
547+
{
548+
// Can't just use ToString or bools will get encoded as True/False instead of true/false.
549+
if (boolValue)
550+
claims.Add(new Claim(keyValuePair.Key, "true", ClaimValueTypes.Boolean, issuer, issuer));
551+
else
552+
claims.Add(new Claim(keyValuePair.Key, "false", ClaimValueTypes.Boolean, issuer, issuer));
553+
}
546554
else if (keyValuePair.Value != null)
547555
claims.Add(new Claim(keyValuePair.Key, keyValuePair.Value.ToString(), GetClaimValueType(keyValuePair.Value), issuer, issuer));
548556
}
@@ -557,6 +565,13 @@ private void AddListofObjects(string key, IEnumerable<object> objects, List<Clai
557565
{
558566
if (obj is string claimValue)
559567
claims.Add(new Claim(key, claimValue, ClaimValueTypes.String, issuer, issuer));
568+
else if (obj is bool boolValue)
569+
{
570+
if (boolValue)
571+
claims.Add(new Claim(key, "true", ClaimValueTypes.Boolean, issuer, issuer));
572+
else
573+
claims.Add(new Claim(key, "false", ClaimValueTypes.Boolean, issuer, issuer));
574+
}
560575
else if (obj is DateTime dateTimeValue)
561576
claims.Add(new Claim(key, dateTimeValue.ToString("o", CultureInfo.InvariantCulture), ClaimValueTypes.DateTime, issuer, issuer));
562577
else if (obj is JsonElement jsonElement)

test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenTests.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,39 @@ public class JsonWebTokenTests
3737
new Claim("float", "42", ClaimValueTypes.Integer32, "LOCAL AUTHORITY", "LOCAL AUTHORITY"),
3838
new Claim("integer", "42", ClaimValueTypes.Integer32, "LOCAL AUTHORITY", "LOCAL AUTHORITY"),
3939
new Claim("nill", "", JsonClaimValueTypes.JsonNull, "LOCAL AUTHORITY", "LOCAL AUTHORITY"),
40-
new Claim("bool", "True", ClaimValueTypes.Boolean, "LOCAL AUTHORITY", "LOCAL AUTHORITY"),
40+
new Claim("bool", "true", ClaimValueTypes.Boolean, "LOCAL AUTHORITY", "LOCAL AUTHORITY"),
4141
new Claim("dateTime", dateTime.ToString(), ClaimValueTypes.String, "LOCAL AUTHORITY", "LOCAL AUTHORITY"),
4242
new Claim("dateTimeIso8061", dateTime.ToUniversalTime().ToString("o", CultureInfo.InvariantCulture), ClaimValueTypes.DateTime, "LOCAL AUTHORITY", "LOCAL AUTHORITY"),
4343
};
4444

45+
[Fact]
46+
public void BoolClaimsEncodedAsExpected()
47+
{
48+
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(new string('a', 128)));
49+
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
50+
51+
var claims = new[] { new Claim("testClaim", "true", ClaimValueTypes.Boolean), new Claim("testClaim2", "True", ClaimValueTypes.Boolean) };
52+
SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
53+
{
54+
SigningCredentials = creds,
55+
Subject = new ClaimsIdentity(claims),
56+
Expires = (new DateTime(2038, 1, 20)).ToUniversalTime(),
57+
};
58+
59+
JsonWebTokenHandler handler = new();
60+
string jwt = handler.CreateToken(tokenDescriptor);
61+
JsonWebToken jsonWebToken = new JsonWebToken(jwt);
62+
63+
var claimSet = jsonWebToken.Claims;
64+
65+
// Will throw if can't find.
66+
var testClaim = claimSet.First(c => c.Type == "testClaim");
67+
Assert.Equal("true", testClaim.Value);
68+
69+
var testClaim2 = claimSet.First(c => c.Type == "testClaim2");
70+
Assert.Equal("true", testClaim2.Value);
71+
}
72+
4573
[Fact]
4674
public void DateTime2038Issue()
4775
{

test/System.IdentityModel.Tokens.Jwt.Tests/JwtPayloadTest.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,8 +256,8 @@ public static TheoryData<string, List<Claim>, JwtPayload, JwtPayload> PayloadDat
256256
new List<Claim>
257257
{
258258
new Claim("ClaimValueTypes.String", "ClaimValueTypes.String.Value", ClaimValueTypes.String),
259-
new Claim("ClaimValueTypes.Boolean.true", "True", ClaimValueTypes.Boolean),
260-
new Claim("ClaimValueTypes.Boolean.false", "False", ClaimValueTypes.Boolean),
259+
new Claim("ClaimValueTypes.Boolean.true", "true", ClaimValueTypes.Boolean),
260+
new Claim("ClaimValueTypes.Boolean.false", "false", ClaimValueTypes.Boolean),
261261
new Claim("ClaimValueTypes.Double", "123.4", ClaimValueTypes.Double),
262262
new Claim("ClaimValueTypes.int.MaxValue", intMaxValue, ClaimValueTypes.Integer32),
263263
new Claim("ClaimValueTypes.int.MinValue", intMinValue, ClaimValueTypes.Integer32),
@@ -300,8 +300,8 @@ public static TheoryData<string, List<Claim>, JwtPayload, JwtPayload> PayloadDat
300300
new Claim("ClaimValueTypes", longValue, ClaimValueTypes.Integer64),
301301
new Claim("ClaimValueTypes", "132.64", ClaimValueTypes.Double),
302302
new Claim("ClaimValueTypes", "-132.64", ClaimValueTypes.Double),
303-
new Claim("ClaimValueTypes", "True", ClaimValueTypes.Boolean),
304-
new Claim("ClaimValueTypes", "False", ClaimValueTypes.Boolean),
303+
new Claim("ClaimValueTypes", "true", ClaimValueTypes.Boolean),
304+
new Claim("ClaimValueTypes", "false", ClaimValueTypes.Boolean),
305305
new Claim("ClaimValueTypes", "2019-11-15T14:31:21.6101326Z", ClaimValueTypes.DateTime),
306306
new Claim("ClaimValueTypes", "2019-11-15", ClaimValueTypes.String),
307307
new Claim("ClaimValueTypes", @"{""name3.1"":""value3.1""}", JsonClaimValueTypes.Json),

test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenTests.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Licensed under the MIT License.
33

44
using System.Collections.Generic;
5+
using System.Linq;
56
using System.Security.Claims;
67
using System.Text;
78
using Microsoft.IdentityModel.Logging;
@@ -13,6 +14,30 @@ namespace System.IdentityModel.Tokens.Jwt.Tests
1314
{
1415
public class JwtSecurityTokenTests
1516
{
17+
[Fact]
18+
public void BoolClaimsEncodedAsExpected()
19+
{
20+
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(new string('a', 128)));
21+
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
22+
23+
var claims = new[] { new Claim("testClaim", "true", ClaimValueTypes.Boolean), new Claim("testClaim2", "True", ClaimValueTypes.Boolean) };
24+
var token = new JwtSecurityToken(
25+
issuer: "issuer.contoso.com",
26+
audience: "audience.contoso.com",
27+
claims: claims,
28+
expires: (new DateTime(2038, 1, 20)).ToUniversalTime(),
29+
signingCredentials: creds);
30+
31+
var claimSet = token.Claims;
32+
33+
// Will throw if can't find.
34+
var testClaim = claimSet.First(c => c.Type == "testClaim");
35+
Assert.Equal("true", testClaim.Value);
36+
37+
var testClaim2 = claimSet.First(c => c.Type == "testClaim2");
38+
Assert.Equal("true", testClaim2.Value);
39+
}
40+
1641
[Fact]
1742
public void DateTime2038Issue()
1843
{

0 commit comments

Comments
 (0)