Skip to content

Commit

Permalink
Fix decoding/encoding payloads with attribute decoration jwt-dotnet#456
Browse files Browse the repository at this point in the history
  • Loading branch information
hartmark committed Jan 24, 2023
1 parent d3b4cea commit b13c8bc
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 3 deletions.
34 changes: 33 additions & 1 deletion src/JWT/Builder/JwtBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Reflection;
using JWT.Algorithms;
using JWT.Serializers;
using Newtonsoft.Json;
using static JWT.Internal.EncodingHelper;

namespace JWT.Builder
Expand Down Expand Up @@ -276,7 +277,7 @@ public string Encode(Type payloadType, object payload)
EnsureCanEncode();

var dic = payloadType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.ToDictionary(prop => prop.Name, prop => prop.GetValue(payload, null));
.ToDictionary(info => GetPropName(info, _jsonSerializerFactory), prop => prop.GetValue(payload, null));

foreach (var pair in dic)
{
Expand All @@ -286,6 +287,37 @@ public string Encode(Type payloadType, object payload)
return Encode();
}

private static string GetPropName(MemberInfo prop, IJsonSerializerFactory jsonSerializerFactory)
{
var customAttributes = prop.GetCustomAttributes(true);
foreach (var attribute in customAttributes)
{
if (jsonSerializerFactory.Create() is JsonNetSerializer)
{
if (attribute is JsonPropertyAttribute jsonNetProperty)
{
return jsonNetProperty.PropertyName;
}
}
#if MODERN_DOTNET
else if (jsonSerializerFactory.Create() is SystemTextSerializer)
{
if (attribute is System.Text.Json.Serialization.JsonPropertyNameAttribute systemTextSerializerProperty)
{
return systemTextSerializerProperty.Name;
}
}
#endif
else
{
throw new NotSupportedException(
$"{jsonSerializerFactory.Create().GetType().Name} is not supported");
}
}

return prop.Name;
}

/// <summary>
/// Decodes a token using the supplied dependencies.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/JWT/JWT.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<Authors>Alexander Batishchev, John Sheehan, Michael Lehenbauer</Authors>
<PackageTags>jwt;json;authorization</PackageTags>
<PackageLicenseExpression>CC0-1.0</PackageLicenseExpression>
<Version>10.0.1</Version>
<Version>10.0.2</Version>
<FileVersion>10.0.0.0</FileVersion>
<AssemblyVersion>10.0.0.0</AssemblyVersion>
<RootNamespace>JWT</RootNamespace>
Expand Down
48 changes: 48 additions & 0 deletions tests/JWT.Tests.Common/Builder/JwtBuilderDecodeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -433,5 +433,53 @@ public void Decode_ToDictionary_Without_Serializer_Should_Throw_Exception()
action.Should()
.Throw<ArgumentNullException>();
}

[TestMethod]
public void Encode_Decode_ToJsonNetDecoratedType_Should_UseDecoratedName_Bug456()
{
var token = JwtBuilder.Create()
.WithAlgorithm(new NoneAlgorithm())
.WithJsonSerializer(new JsonNetSerializer());

var model = new TestData.TestDataJsonNetDecorated
{
AccessToken = "abc123",
};

var encoded = token.Encode(model);
Assert.IsNotNull(encoded);

token = JwtBuilder.Create()
.WithAlgorithm(new NoneAlgorithm())
.WithJsonSerializer(new JsonNetSerializer());

var payloadDecoded = token.Decode<TestData.TestDataJsonNetDecorated>(encoded);
Assert.AreEqual(model.AccessToken, payloadDecoded.AccessToken);
}
#if NETSTANDARD2_0 || NET6_0 || NET7_0

[TestMethod]
public void Encode_Decode_ToSystemTextSerializerDecoratedType_Should_UseDecoratedName_Bug456()
{
var token = JwtBuilder.Create()
.WithAlgorithm(new NoneAlgorithm())
.WithJsonSerializer(new SystemTextSerializer());

var model = new TestData.TestDataSystemTextSerializerDecorated
{
AccessToken = "abc123",
};

var encoded = token.Encode(model);
Assert.IsNotNull(encoded);

token = JwtBuilder.Create()
.WithAlgorithm(new NoneAlgorithm())
.WithJsonSerializer(new SystemTextSerializer());

var payloadDecoded = token.Decode<TestData.TestDataSystemTextSerializerDecorated>(encoded);
Assert.AreEqual(model.AccessToken, payloadDecoded.AccessToken);
}
#endif
}
}
2 changes: 1 addition & 1 deletion tests/JWT.Tests.Common/Builder/JwtBuilderEncodeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ public void Encode_With_Secret_Should_Return_Valid_Token_Using_Json_Net()
.HaveCount(3, "because the token should consist of three parts");
}

#if NETSTANDARD2_0 || NET6_0
#if NETSTANDARD2_0 || NET6_0 || NET7_0
[TestMethod]
public void Encode_Test_Bug438()
{
Expand Down
14 changes: 14 additions & 0 deletions tests/JWT.Tests.Common/Models/TestData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ public static class TestData
Age = 33
};

public class TestDataJsonNetDecorated
{
[Newtonsoft.Json.JsonProperty("AT")]
public string AccessToken { get; set; }
}

#if NETSTANDARD2_0 || NET6_0 || NET7_0
public class TestDataSystemTextSerializerDecorated
{
[System.Text.Json.Serialization.JsonPropertyName("AT")]
public string AccessToken { get; set; }
}
#endif

public const string Secret = "GQDstcKsx0NHjPOuXOYg5MbeJ1XT0uFiwDVvVBrk";
public const string Secret2 = "QWORIJkmQWEDIHbjhOIHAUSDFOYnUGWEYT";

Expand Down

0 comments on commit b13c8bc

Please sign in to comment.