Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@
<Reference Include="System.Runtime.Extensions" />
<Reference Include="System.Security.Principal" />
<Reference Include="System.Threading.Thread" />
<Reference Include="System.Text.Json" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.IO;
using System.Runtime.Serialization;
using System.Security.Principal;
using System.Text.Json;

namespace System.Security.Claims
{
Expand Down Expand Up @@ -698,14 +699,38 @@ public virtual bool HasClaim(string type, string value)

foreach (Claim claim in Claims)
{
if (claim != null
&& string.Equals(claim.Type, type, StringComparison.OrdinalIgnoreCase)
&& string.Equals(claim.Value, value, StringComparison.Ordinal))
if (string.Equals(claim.Type, type, StringComparison.OrdinalIgnoreCase))
{
return true;
if (claim.Value != null)
{
if (string.Equals(claim.Value, value, StringComparison.Ordinal))
{
return true;
}
else if (claim.Value.Trim().StartsWith("[") && claim.Value.Trim().EndsWith("]"))
{
try
{
string[]? claimValues = JsonSerializer.Deserialize<string[]>(claim.Value.ToString());

if (claimValues != null)
{
foreach (string claimValue in claimValues)
{
if (string.Equals(claimValue, value, StringComparison.Ordinal))
{
return true;
}
}
}
}
catch (JsonException)
{
}
}
}
}
}

return false;
}

Expand Down
23 changes: 23 additions & 0 deletions src/libraries/System.Security.Claims/tests/ClaimsIdentityTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,29 @@ public void HasClaim_TypeValue()
Assert.False(id.HasClaim("claim_type", "Xclaim_value"));
}

[Fact]
public void HasClaim_TypeArrayValue()
{
var id = new ClaimsIdentity(
new[] {
new Claim ("claim_type", "claim_value"),
new Claim ("multi_value_type", "[\"claim_value1\",\"claim_value2\"]"),
new Claim ("claim_type_with_symbol", "[claim_value]"),
}, "test_authority");

Assert.True(id.HasClaim("claim_type_with_symbol", "[claim_value]"));
Assert.True(id.HasClaim("Claim_type_with_symbOl", "[claim_value]"));
Assert.True(id.HasClaim("multi_value_type", "claim_value1"));
Assert.True(id.HasClaim("multi_value_type", "claim_value2"));
Assert.True(id.HasClaim("multi_Value_tyPe", "claim_value1"));
Assert.True(id.HasClaim("mUlti_vaLue_type", "claim_value2"));
Assert.False(id.HasClaim("claim_type_with_symbol", "claim_value1"));
Assert.False(id.HasClaim("claim_type_with_symbol", "[clAim_vaLue]"));
Assert.False(id.HasClaim("multi_value_type", "cLaIm_VaLuE1"));
Assert.False(id.HasClaim("Xmulti_value_type", "claim_value1"));
Assert.False(id.HasClaim("multi_value_type", "Xclaim_value1"));
}

[Serializable]
private sealed class CustomClaimsIdentity : ClaimsIdentity, ISerializable
{
Expand Down