Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Microsoft.IdentityModel.JsonWebTokens.JsonWebToken.TryReadJwtClaim.get -> Microsoft.IdentityModel.Tokens.TryReadJwtClaim
Microsoft.IdentityModel.JsonWebTokens.JsonWebToken.TryReadJwtClaim.set -> void
virtual Microsoft.IdentityModel.JsonWebTokens.JsonWebToken.ReadHeaderValue(ref System.Text.Json.Utf8JsonReader reader, System.Collections.Generic.IDictionary<string, object> claims) -> void

10 changes: 7 additions & 3 deletions src/Microsoft.IdentityModel.JsonWebTokens/Json/JsonClaimSet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ internal class JsonClaimSet

internal JsonClaimSet()
{
_jsonClaims = new Dictionary<string, object>();
_jsonClaims = [];
}

internal JsonClaimSet(Dictionary<string, object> jsonClaims)
Expand Down Expand Up @@ -88,9 +88,9 @@ internal static void CreateClaimFromObject(List<Claim> claims, string claimType,
claims.Add(new Claim(claimType, m.ToString(CultureInfo.InvariantCulture), ClaimValueTypes.Double, issuer, issuer));
else if (value is null)
claims.Add(new Claim(claimType, string.Empty, JsonClaimValueTypes.JsonNull, issuer, issuer));
else if (value is IList ilist)
else if (value is IList iList)
{
foreach (var item in ilist)
foreach (var item in iList)
CreateClaimFromObject(claims, claimType, item, issuer);
}
else if (value is JsonElement j)
Expand All @@ -109,6 +109,10 @@ internal static void CreateClaimFromObject(List<Claim> claims, string claimType,
if (claim != null)
claims.Add(claim);
}
else
{
claims.Add(new Claim(claimType, value.ToString(), ClaimValueTypes.String, issuer, issuer));
}
}

internal static Claim CreateClaimFromJsonElement(string claimType, string issuer, JsonElement jsonElement)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Collections.Generic;
using System.Text.Json;
using Microsoft.IdentityModel.Logging;
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Tokens.Json;

namespace Microsoft.IdentityModel.JsonWebTokens
Expand Down Expand Up @@ -41,41 +42,7 @@ internal JsonClaimSet CreateHeaderClaimSet(ReadOnlySpan<byte> byteSpan)
{
if (reader.TokenType == JsonTokenType.PropertyName)
{
if (reader.ValueTextEquals(JwtHeaderUtf8Bytes.Alg))
{
_alg = JsonSerializerPrimitives.ReadString(ref reader, JwtHeaderParameterNames.Alg, ClassName, true);
claims[JwtHeaderParameterNames.Alg] = _alg;
}
else if (reader.ValueTextEquals(JwtHeaderUtf8Bytes.Cty))
{
_cty = JsonSerializerPrimitives.ReadString(ref reader, JwtHeaderParameterNames.Cty, ClassName, true);
claims[JwtHeaderParameterNames.Cty] = _cty;
}
else if (reader.ValueTextEquals(JwtHeaderUtf8Bytes.Kid))
{
_kid = JsonSerializerPrimitives.ReadString(ref reader, JwtHeaderParameterNames.Kid, ClassName, true);
claims[JwtHeaderParameterNames.Kid] = _kid;
}
else if (reader.ValueTextEquals(JwtHeaderUtf8Bytes.Typ))
{
_typ = JsonSerializerPrimitives.ReadString(ref reader, JwtHeaderParameterNames.Typ, ClassName, true);
claims[JwtHeaderParameterNames.Typ] = _typ;
}
else if (reader.ValueTextEquals(JwtHeaderUtf8Bytes.X5t))
{
_x5t = JsonSerializerPrimitives.ReadString(ref reader, JwtHeaderParameterNames.X5t, ClassName, true);
claims[JwtHeaderParameterNames.X5t] = _x5t;
}
else if (reader.ValueTextEquals(JwtHeaderUtf8Bytes.Zip))
{
_zip = JsonSerializerPrimitives.ReadString(ref reader, JwtHeaderParameterNames.Zip, ClassName, true);
claims[JwtHeaderParameterNames.Zip] = _zip;
}
else
{
string propertyName = reader.GetString();
claims[propertyName] = JsonSerializerPrimitives.ReadPropertyValueAsObject(ref reader, propertyName, JsonClaimSet.ClassName, true);
}
ReadHeaderValue(ref reader, claims);
}
// We read a JsonTokenType.StartObject above, exiting and positioning reader at next token.
else if (JsonSerializerPrimitives.IsReaderAtTokenType(ref reader, JsonTokenType.EndObject, false))
Expand All @@ -86,5 +53,65 @@ internal JsonClaimSet CreateHeaderClaimSet(ReadOnlySpan<byte> byteSpan)

return new JsonClaimSet(claims);
}


/// <summary>
/// Reads the value of a claim in the header and adds it to the <paramref name="claims"/> dictionary.
/// Can be overridden to read and add custom claims.
/// If a custom claim is read, the reader should be positioned at the next token after reading the claim.
/// </summary>
/// <param name="reader">The Utf8JsonReader instance positioned at a claim name token used to read the JSON payload.</param>
/// <param name="claims">Collection of claims that have been read from the reader.</param>
private protected virtual void ReadHeaderValue(ref Utf8JsonReader reader, IDictionary<string, object> claims)
{
if (reader.ValueTextEquals(JwtHeaderUtf8Bytes.Alg))
{
claims[JwtHeaderParameterNames.Alg] = JsonSerializerPrimitives.ReadString(ref reader, JwtHeaderParameterNames.Alg, ClassName, true);
}
else if (reader.ValueTextEquals(JwtHeaderUtf8Bytes.Cty))
{
claims[JwtHeaderParameterNames.Cty] = JsonSerializerPrimitives.ReadString(ref reader, JwtHeaderParameterNames.Cty, ClassName, true);
}
else if (reader.ValueTextEquals(JwtHeaderUtf8Bytes.Kid))
{
claims[JwtHeaderParameterNames.Kid] = JsonSerializerPrimitives.ReadString(ref reader, JwtHeaderParameterNames.Kid, ClassName, true);
}
else if (reader.ValueTextEquals(JwtHeaderUtf8Bytes.Typ))
{
claims[JwtHeaderParameterNames.Typ] = JsonSerializerPrimitives.ReadString(ref reader, JwtHeaderParameterNames.Typ, ClassName, true); ;
}
else if (reader.ValueTextEquals(JwtHeaderUtf8Bytes.X5t))
{
claims[JwtHeaderParameterNames.X5t] = JsonSerializerPrimitives.ReadString(ref reader, JwtHeaderParameterNames.X5t, ClassName, true);
}
else if (reader.ValueTextEquals(JwtHeaderUtf8Bytes.Zip))
{
claims[JwtHeaderParameterNames.Zip] = JsonSerializerPrimitives.ReadString(ref reader, JwtHeaderParameterNames.Zip, ClassName, true);
}
else
{
string claimName = reader.GetString();

if (TryReadJwtClaim != null)
{
reader.Read(); // Move to the value
if (TryReadJwtClaim(ref reader, JwtSegmentType.Header, claimName, out object claimValue))
{
claims[claimName] = claimValue;
reader.Read(); // Move to the next token
}
else
{
// The reader is positioned at the value token. The custom delegate did not read the value. Use our own logic.
claims[claimName] = JsonSerializerPrimitives.ReadPropertyValueAsObject(ref reader, claimName, JsonClaimSet.ClassName, false);
}
}
else
{
// Move the reader forward to the value and read it using our own logic.
claims[claimName] = JsonSerializerPrimitives.ReadPropertyValueAsObject(ref reader, claimName, JsonClaimSet.ClassName, true);
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,18 @@ internal JsonClaimSet CreatePayloadClaimSet(ReadOnlySpan<byte> byteSpan)
return new JsonClaimSet(claims);
}

/// <summary>
/// Reads the value of a claim in the payload and adds it to the <paramref name="claims"/> dictionary.
/// Can be overridden to read and add custom claims.
/// If a custom claim is read, the reader should be positioned at the next token after reading the claim.
/// </summary>
/// <param name="reader">The Utf8JsonReader instance positioned at a claim name token used to read the JSON payload.</param>
/// <param name="claims">Collection of claims that have been read from the reader.</param>
private protected virtual void ReadPayloadValue(ref Utf8JsonReader reader, IDictionary<string, object> claims)
{
if (reader.ValueTextEquals(JwtPayloadUtf8Bytes.Aud))
{
_audiences = [];
List<string> _audiences = [];
reader.Read();
if (reader.TokenType == JsonTokenType.StartArray)
{
Expand All @@ -78,46 +85,55 @@ private protected virtual void ReadPayloadValue(ref Utf8JsonReader reader, IDict
}
else if (reader.ValueTextEquals(JwtPayloadUtf8Bytes.Azp))
{
_azp = JsonSerializerPrimitives.ReadString(ref reader, JwtRegisteredClaimNames.Azp, ClassName, true);
claims[JwtRegisteredClaimNames.Azp] = _azp;
claims[JwtRegisteredClaimNames.Azp] = JsonSerializerPrimitives.ReadString(ref reader, JwtRegisteredClaimNames.Azp, ClassName, true);
}
else if (reader.ValueTextEquals(JwtPayloadUtf8Bytes.Exp))
{
_exp = JsonSerializerPrimitives.ReadLong(ref reader, JwtRegisteredClaimNames.Exp, ClassName, true);
_expDateTime = EpochTime.DateTime(_exp.Value);
claims[JwtRegisteredClaimNames.Exp] = _exp;
claims[JwtRegisteredClaimNames.Exp] = JsonSerializerPrimitives.ReadLong(ref reader, JwtRegisteredClaimNames.Exp, ClassName, true);
}
else if (reader.ValueTextEquals(JwtPayloadUtf8Bytes.Iat))
{
_iat = JsonSerializerPrimitives.ReadLong(ref reader, JwtRegisteredClaimNames.Iat, ClassName, true);
_iatDateTime = EpochTime.DateTime(_iat.Value);
claims[JwtRegisteredClaimNames.Iat] = _iat;
claims[JwtRegisteredClaimNames.Iat] = JsonSerializerPrimitives.ReadLong(ref reader, JwtRegisteredClaimNames.Iat, ClassName, true);
}
else if (reader.ValueTextEquals(JwtPayloadUtf8Bytes.Iss))
{
_iss = JsonSerializerPrimitives.ReadString(ref reader, JwtRegisteredClaimNames.Iss, ClassName, true);
claims[JwtRegisteredClaimNames.Iss] = _iss;
claims[JwtRegisteredClaimNames.Iss] = JsonSerializerPrimitives.ReadString(ref reader, JwtRegisteredClaimNames.Iss, ClassName, true);
}
else if (reader.ValueTextEquals(JwtPayloadUtf8Bytes.Jti))
{
_jti = JsonSerializerPrimitives.ReadString(ref reader, JwtRegisteredClaimNames.Jti, ClassName, true);
claims[JwtRegisteredClaimNames.Jti] = _jti;
claims[JwtRegisteredClaimNames.Jti] = JsonSerializerPrimitives.ReadString(ref reader, JwtRegisteredClaimNames.Jti, ClassName, true);
}
else if (reader.ValueTextEquals(JwtPayloadUtf8Bytes.Nbf))
{
_nbf = JsonSerializerPrimitives.ReadLong(ref reader, JwtRegisteredClaimNames.Nbf, ClassName, true);
_nbfDateTime = EpochTime.DateTime(_nbf.Value);
claims[JwtRegisteredClaimNames.Nbf] = _nbf;
claims[JwtRegisteredClaimNames.Nbf] = JsonSerializerPrimitives.ReadLong(ref reader, JwtRegisteredClaimNames.Nbf, ClassName, true);
}
else if (reader.ValueTextEquals(JwtPayloadUtf8Bytes.Sub))
{
_sub = JsonSerializerPrimitives.ReadStringOrNumberAsString(ref reader, JwtRegisteredClaimNames.Sub, ClassName, true);
claims[JwtRegisteredClaimNames.Sub] = _sub;
claims[JwtRegisteredClaimNames.Sub] = JsonSerializerPrimitives.ReadStringOrNumberAsString(ref reader, JwtRegisteredClaimNames.Sub, ClassName, true);
}
else
{
string propertyName = reader.GetString();
claims[propertyName] = JsonSerializerPrimitives.ReadPropertyValueAsObject(ref reader, propertyName, JsonClaimSet.ClassName, true);
string claimName = reader.GetString();

if (TryReadJwtClaim != null)
{
reader.Read(); // Move to the value
if (TryReadJwtClaim(ref reader, JwtSegmentType.Payload, claimName, out object claimValue))
{
claims[claimName] = claimValue;
reader.Read(); // Move to the next token
}
else
{
// The reader is positioned at the value token. The custom delegate did not read the value. Use our own logic.
claims[claimName] = JsonSerializerPrimitives.ReadPropertyValueAsObject(ref reader, claimName, JsonClaimSet.ClassName, false);
}
}
else
{
// Move the reader forward to the value and read it using our own logic.
claims[claimName] = JsonSerializerPrimitives.ReadPropertyValueAsObject(ref reader, claimName, JsonClaimSet.ClassName, true);
}
}
}
}
Expand Down
Loading
Loading