Skip to content

Commit

Permalink
Fixed deserializing JWT header (#459)
Browse files Browse the repository at this point in the history
* Fixed deserializing JWT header
* Updated Newtonsoft.Json to version to 13.0.2
* Updated System.Text.Json to version 6.0.7
* Updated Microsoft.NET.Test.Sdk to version 17.4.1
* Bumped version of JWT to 10.0.1
* Bumped version of JWT.Extensions.AspNetCore to 10.0.01
* Bumped version of JWT.Extensions.DependencyInjection to 2.2.1
  • Loading branch information
abatishchev authored Jan 18, 2023
1 parent 0b3bd0b commit ebc0945
Show file tree
Hide file tree
Showing 14 changed files with 104 additions and 42 deletions.
11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,14 @@ indent_style = space;
indent_size = 4;
insert_final_newline = false;
trim_trailing_whitespace = true;

## IDE

# IDE0003: Remove qualification
dotnet_style_qualification_for_property = true:warning

# IDE0049: Simplify Names
dotnet_style_predefined_type_for_member_access = false

# IDE0090: Use 'new(...)'
csharp_style_implicit_object_creation_when_type_is_apparent = false
32 changes: 19 additions & 13 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
# Unreleased

- TBD

# 10.0.0

- Made NoneAlgorithm not requiring any keys as it is not signed
- Added option to select default serializer, Newtonsoft.Json or System.Text.Json (#433)
- Renamed default IdentityFactory in Jwt.Extensions.AspNetCore, opened up for inheritance, extension (#428)
- Added Encode(T) and Encode(Type, object) to JwtBuilder (#415)
- Bumped Newtonsoft.Json from 10.0.3 to 13.0.1
- Fixed typos in exception messages
- Made verify=true by default in IJwtDecoder methods
# Unreleased

- TBD

# 10.0.1

- Fixed deserializing JWT header
- Updated Newtonsoft.Json to version to 13.0.2
- Updated System.Text.Json to version 6.0.7

# 10.0.0

- Made NoneAlgorithm not requiring any keys as it is not signed
- Added option to select default serializer, Newtonsoft.Json or System.Text.Json (#433)
- Renamed default IdentityFactory in Jwt.Extensions.AspNetCore, opened up for inheritance, extension (#428)
- Added Encode(T) and Encode(Type, object) to JwtBuilder (#415)
- Updated Newtonsoft.Json to version 13.0.1
- Fixed typos in exception messages
- Made verify=true by default in IJwtDecoder methods
1 change: 1 addition & 0 deletions JWT.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_", "_", "{513CE2B5-E0D6-43
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
.gitignore = .gitignore
CHANGELOG.md = CHANGELOG.md
Directory.Build.props = Directory.Build.props
JWT.sln.DotSettings = JWT.sln.DotSettings
JwtStrongNameKey.snk = JwtStrongNameKey.snk
Expand Down
1 change: 0 additions & 1 deletion JWT.sln.DotSettings
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/CodeFormatting/CSharpCodeStyle/ThisQualifier/INSTANCE_MEMBERS_QUALIFY_MEMBERS/@EntryValue">Property</s:String>
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue"></s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HMACSHA/@EntryIndexedValue">HMACSHA</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RS/@EntryIndexedValue">RS</s:String>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<Authors>Alexander Batishchev</Authors>
<PackageTags>jwt;json;asp.net;asp.net core;.net core;authorization</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Version>10.0.0</Version>
<Version>10.0.1</Version>
<FileVersion>10.0.0.0</FileVersion>
<AssemblyVersion>10.0.0.0</AssemblyVersion>
<RootNamespace>JWT.Extensions.AspNetCore</RootNamespace>
Expand All @@ -30,8 +30,8 @@

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="2.2.0" />
<PackageReference Condition="$(DefineConstants.Contains(MODERN_DOTNET))" Include="System.Text.Json" Version="6.0.4" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="System.Text.Json" Version="6.0.7" Condition="$(DefineConstants.Contains(MODERN_DOTNET))" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<Authors>Alexander Batishchev</Authors>
<PackageTags>jwt;json;asp.net;asp.net core;.net core;authorization;dependenсy injection</PackageTags>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Version>2.2.0</Version>
<Version>2.2.1</Version>
<FileVersion>2.0.0.0</FileVersion>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
<RootNamespace>JWT</RootNamespace>
Expand All @@ -30,8 +30,8 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="3.1.25" />
<PackageReference Condition="$(DefineConstants.Contains(MODERN_DOTNET))" Include="System.Text.Json" Version="6.0.4" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Condition="$(DefineConstants.Contains(MODERN_DOTNET))" Include="System.Text.Json" Version="6.0.7" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>

<ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions src/JWT/Builder/JwtData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public JwtData()
/// <summary>
/// Creates a new instance of <see cref="JwtData" />
/// </summary>
/// <param name="payload">Dictionary that contans the payload</param>
/// <param name="payload">Dictionary that contains the payload</param>
public JwtData(IDictionary<string, object> payload)
: this(null, payload)
{
Expand All @@ -31,7 +31,7 @@ public JwtData(IDictionary<string, object> payload)
/// Creates a new instance of <see cref="JwtData" />
/// </summary>
/// <param name="header">Dictionary that contains the headers</param>
/// <param name="payload">Dictionary that contans the payload</param>
/// <param name="payload">Dictionary that contains the payload</param>
public JwtData(IDictionary<string, object> header, IDictionary<string, object> payload)
{
this.Header = header ?? new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
Expand Down
27 changes: 24 additions & 3 deletions src/JWT/Builder/JwtHeader.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#if MODERN_DOTNET
using JsonProperty = System.Text.Json.Serialization.JsonPropertyNameAttribute;
#else
using Newtonsoft.Json;
using System.Text.Json.Serialization;
#endif

using Newtonsoft.Json;

namespace JWT.Builder
{
/// <summary>
Expand All @@ -12,24 +12,45 @@ namespace JWT.Builder
public class JwtHeader
{
[JsonProperty("typ")]
#if MODERN_DOTNET
[JsonPropertyName("typ")]
#endif
public string Type { get; set; }

[JsonProperty("cty")]
#if MODERN_DOTNET
[JsonPropertyName("cty")]
#endif
public string ContentType { get; set; }

[JsonProperty("alg")]
#if MODERN_DOTNET
[JsonPropertyName("alg")]
#endif
public string Algorithm { get; set; }

[JsonProperty("kid")]
#if MODERN_DOTNET
[JsonPropertyName("kid")]
#endif
public string KeyId { get; set; }

[JsonProperty("x5u")]
#if MODERN_DOTNET
[JsonPropertyName("x5u")]
#endif
public string X5u { get; set; }

[JsonProperty("x5c")]
#if MODERN_DOTNET
[JsonPropertyName("x5c")]
#endif
public string[] X5c { get; set; }

[JsonProperty("x5t")]
#if MODERN_DOTNET
[JsonPropertyName("x5t")]
#endif
public string X5t { get; set; }
}
}
8 changes: 4 additions & 4 deletions src/JWT/JWT.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netstandard1.3;netstandard2.0;net6.0;net35;net40;net462;</TargetFrameworks>
Expand All @@ -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.0</Version>
<Version>10.0.1</Version>
<FileVersion>10.0.0.0</FileVersion>
<AssemblyVersion>10.0.0.0</AssemblyVersion>
<RootNamespace>JWT</RootNamespace>
Expand All @@ -38,8 +38,8 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Condition="$(DefineConstants.Contains(MODERN_DOTNET))" Include="System.Text.Json" Version="6.0.4" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Condition="$(DefineConstants.Contains(MODERN_DOTNET))" Include="System.Text.Json" Version="6.0.7" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>

<ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.3' OR '$(TargetFramework)' == 'netstandard2.0'">
Expand Down
9 changes: 8 additions & 1 deletion src/JWT/JwtDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,11 +294,18 @@ private static bool AllKeysHaveValues(byte[][] keys)
private void ValidateNoneAlgorithm(JwtParts jwt)
{
var header = DecodeHeader<JwtHeader>(jwt);

if (String.IsNullOrEmpty(header.Type) &&
String.IsNullOrEmpty(header.Algorithm))
{
throw new InvalidOperationException("Error deserializing JWT header, all mandatory properties are null or empty");
}

if (String.Equals(header.Algorithm, nameof(JwtAlgorithmName.None), StringComparison.OrdinalIgnoreCase) &&
!String.IsNullOrEmpty(jwt.Signature))
{
throw new InvalidOperationException("Signature is not acceptable for algorithm None");
}
}
}
}
}
2 changes: 1 addition & 1 deletion tests/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
<ItemGroup>
<PackageReference Include="AutoFixture" Version="4.17.0" />
<PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="MSTest.TestAdapter" Version="3.0.2" />
<PackageReference Include="MSTest.TestFramework" Version="3.0.2" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="3.1.25" Condition="'$(TargetFramework)' == 'netcoreapp3.1'" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="6.0.5" Condition="'$(TargetFramework)' == 'net6.0'" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
<PackageReference Include="System.Text.Json" Version="6.0.4" />
<PackageReference Include="System.Text.Json" Version="6.0.7" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="MSTest.TestAdapter" Version="2.2.10" />
<PackageReference Include="MSTest.TestFramework" Version="2.2.10" />
</ItemGroup>

<ItemGroup>
Expand Down
31 changes: 27 additions & 4 deletions tests/JWT.Tests.Common/Builder/JwtBuilderDecodeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using FluentAssertions;
using JWT.Algorithms;
using JWT.Builder;
using JWT.Serializers;
using JWT.Tests.Models;
using Microsoft.VisualStudio.TestTools.UnitTesting;

Expand Down Expand Up @@ -82,7 +83,7 @@ public void Decode_Using_Asymmetric_Algorithm_Should_Return_Token()
}

[TestMethod]
public void Decode_Using_Signature_Is_Not_Accepted_For_None_Algorithm()
public void Decode_Using_Signature_For_None_Algorithm_Should_Throw_Exception()
{
Action action =
() => JwtBuilder.Create()
Expand All @@ -107,7 +108,7 @@ public void Decode_Using_Empty_Signature_Should_Work_For_None_Algorithm()
}

[TestMethod]
public void Decode_With_MustVerifySignature_Should_Not_Be_Allowed_For_For_None_Algorithm()
public void Decode_With_MustVerifySignature_For_None_Algorithm_Should_Throw_Exception()
{
Action action =
() => JwtBuilder.Create()
Expand All @@ -118,9 +119,31 @@ public void Decode_With_MustVerifySignature_Should_Not_Be_Allowed_For_For_None_A
action.Should()
.Throw<InvalidOperationException>("verify signature is not supported for none algorithm");
}


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

var encodedModel = token.Encode(TestData.Customer);
encodedModel.Should()
.NotBeNullOrEmpty();

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

var decodedModel = token.Decode<Customer>(encodedModel);
decodedModel.Should()
.NotBeNull();
}

[TestMethod]
public void Decode_Using_No_Secret_Should_Work_For_None_Algorithm()
public void Decode_With_No_Secret_Should_Return_Token_For_None_Algorithm()
{
var token = JwtBuilder.Create()
.WithAlgorithm(new NoneAlgorithm())
Expand Down

0 comments on commit ebc0945

Please sign in to comment.