From 0381094aff8b29a3c48ae4003d46de96efd66cdf Mon Sep 17 00:00:00 2001 From: Markus Hartung Date: Fri, 9 Sep 2022 01:09:38 +0200 Subject: [PATCH] NoneAlgorithm should not require any keys as it is not signed (#435) * NoneAlgorithm should not require any keys as it is not signed * Updated tests * Bumped version of JWT to 10.0.0-beta8 Co-authored-by: Alexander Batishchev --- src/JWT/JWT.csproj | 2 +- src/JWT/JwtEncoder.cs | 2 +- .../Builder/JwtBuilderDecodeTests.cs | 11 ++++++ .../Builder/JwtBuilderEncodeTests.cs | 20 +++++++++- tests/JWT.Tests.Common/JwtEncoderTests.cs | 37 ++++++++++++++----- 5 files changed, 59 insertions(+), 13 deletions(-) diff --git a/src/JWT/JWT.csproj b/src/JWT/JWT.csproj index 7d891e154..63847778f 100644 --- a/src/JWT/JWT.csproj +++ b/src/JWT/JWT.csproj @@ -20,7 +20,7 @@ Alexander Batishchev, John Sheehan, Michael Lehenbauer jwt;json;authorization CC0-1.0 - 10.0.0-beta7 + 10.0.0-beta8 10.0.0.0 10.0.0.0 JWT diff --git a/src/JWT/JwtEncoder.cs b/src/JWT/JwtEncoder.cs index b274ef194..126e9f7c1 100644 --- a/src/JWT/JwtEncoder.cs +++ b/src/JWT/JwtEncoder.cs @@ -49,7 +49,7 @@ public string Encode(IDictionary extraHeaders, object payload, b var algorithm = _algFactory.Create(null); if (algorithm is null) throw new ArgumentNullException(nameof(algorithm)); - if (!algorithm.IsAsymmetric() && key is null) + if (!algorithm.IsAsymmetric() && key is null && algorithm is not NoneAlgorithm) throw new ArgumentNullException(nameof(key)); var header = extraHeaders is null ? diff --git a/tests/JWT.Tests.Common/Builder/JwtBuilderDecodeTests.cs b/tests/JWT.Tests.Common/Builder/JwtBuilderDecodeTests.cs index 904144b3d..911be2ffc 100644 --- a/tests/JWT.Tests.Common/Builder/JwtBuilderDecodeTests.cs +++ b/tests/JWT.Tests.Common/Builder/JwtBuilderDecodeTests.cs @@ -119,6 +119,17 @@ public void Decode_With_MustVerifySignature_Should_Not_Be_Allowed_For_For_None_A .Throw("verify signature is not supported for none algorithm"); } + [TestMethod] + public void Decode_Using_No_Secret_Should_Work_For_None_Algorithm() + { + var token = JwtBuilder.Create() + .WithAlgorithm(new NoneAlgorithm()) + .Decode(TestData.TokenWithAlgNoneMissingSignature); + + token.Should() + .NotBeNullOrEmpty("Using none algorithm should be valid without any secret"); + } + [TestMethod] public void Decode_With_VerifySignature_And_Without_Algorithm_Should_Throw_Exception() { diff --git a/tests/JWT.Tests.Common/Builder/JwtBuilderEncodeTests.cs b/tests/JWT.Tests.Common/Builder/JwtBuilderEncodeTests.cs index 101776d73..46c2852a0 100644 --- a/tests/JWT.Tests.Common/Builder/JwtBuilderEncodeTests.cs +++ b/tests/JWT.Tests.Common/Builder/JwtBuilderEncodeTests.cs @@ -139,7 +139,7 @@ public void Encode_With_MultipleSecrets_Should_Throw_Exception() } [TestMethod] - public void Encode_WithoutAlgorithm_Should_Return_Token() + public void Encode_With_NoneAlgorithm_Should_Return_Token() { var secret = _fixture.Create(); @@ -158,6 +158,24 @@ public void Encode_WithoutAlgorithm_Should_Return_Token() .Should() .BeEmpty("Because it should miss signature"); } + + [TestMethod] + public void Encode_With_NoneAlgorithm_Should_Not_Require_Secret() + { + var token = JwtBuilder.Create() + .WithAlgorithm(new NoneAlgorithm()) + .Encode(); + + token.Should() + .NotBeNullOrEmpty("because the token should contains some data"); + token.Split('.') + .Should() + .HaveCount(3, "because the token should consist of three parts"); + token.Split('.') + .Last() + .Should() + .BeEmpty("Because it should miss signature"); + } [TestMethod] public void Encode_Should_Return_Token_With_Extra_Headers() diff --git a/tests/JWT.Tests.Common/JwtEncoderTests.cs b/tests/JWT.Tests.Common/JwtEncoderTests.cs index 8f67455ee..873e167ed 100644 --- a/tests/JWT.Tests.Common/JwtEncoderTests.cs +++ b/tests/JWT.Tests.Common/JwtEncoderTests.cs @@ -14,7 +14,7 @@ public class JwtEncoderTests public void Encode_Should_Encode_To_Token() { const string key = TestData.Secret; - var toEncode = TestData.Customer; + var customer = TestData.Customer; const string expected = TestData.Token; var algorithm = new HMACSHA256Algorithm(); @@ -22,7 +22,7 @@ public void Encode_Should_Encode_To_Token() var serializer = CreateSerializer(); var encoder = new JwtEncoder(algorithm, serializer, urlEncoder); - var actual = encoder.Encode(toEncode, key); + var actual = encoder.Encode(customer, key); actual.Should() .Be(expected, "because the same data encoded with the same key must result in the same token"); @@ -36,7 +36,7 @@ public void Encode_Should_Encode_To_Token_With_Extra_Headers() { "foo", "bar" } }; const string key = TestData.Secret; - var toEncode = TestData.Customer; + var customer = TestData.Customer; const string expected = TestData.TokenWithExtraHeaders; var algorithm = new HMACSHA256Algorithm(); @@ -44,7 +44,7 @@ public void Encode_Should_Encode_To_Token_With_Extra_Headers() var serializer = CreateSerializer(); var encoder = new JwtEncoder(algorithm, serializer, urlEncoder); - var actual = encoder.Encode(extraHeaders, toEncode, key); + var actual = encoder.Encode(extraHeaders, customer, key); actual.Should() .Be(expected, "because the same data encoded with the same key must result in the same token"); @@ -58,7 +58,7 @@ public void Encode_Should_Encode_To_Token_With_Custom_Type_Headers() { "typ", "foo" } }; const string key = TestData.Secret; - var toEncode = TestData.Customer; + var customer = TestData.Customer; const string expected = TestData.TokenWithCustomTypeHeader; var algorithm = new HMACSHA256Algorithm(); @@ -66,7 +66,7 @@ public void Encode_Should_Encode_To_Token_With_Custom_Type_Headers() var serializer = CreateSerializer(); var encoder = new JwtEncoder(algorithm, serializer, urlEncoder); - var actual = encoder.Encode(extraHeaders, toEncode, key); + var actual = encoder.Encode(extraHeaders, customer, key); actual.Should() .Be(expected, "because the same data encoded with the same key must result in the same token"); @@ -76,7 +76,7 @@ public void Encode_Should_Encode_To_Token_With_Custom_Type_Headers() public void Encode_With_NoAlgorithm_Should_Encode_To_Token() { const string key = TestData.Secret; - var toEncode = TestData.Customer; + var customer = TestData.Customer; const string expected = TestData.TokenWithoutSignature; var algorithm = new NoneAlgorithm(); @@ -84,7 +84,7 @@ public void Encode_With_NoAlgorithm_Should_Encode_To_Token() var serializer = CreateSerializer(); var encoder = new JwtEncoder(algorithm, serializer, urlEncoder); - var actual = encoder.Encode(toEncode, key); + var actual = encoder.Encode(customer, key); actual.Should() .Be(expected, "because the same data encoded with the same key must result in the same token"); @@ -94,7 +94,7 @@ public void Encode_With_NoAlgorithm_Should_Encode_To_Token() public void Encode_Should_Encode_To_Token_Using_Json_Net() { const string key = TestData.Secret; - var toEncode = TestData.Customer; + var customer = TestData.Customer; const string expected = TestData.Token; var algorithm = new HMACSHA256Algorithm(); @@ -102,7 +102,7 @@ public void Encode_Should_Encode_To_Token_Using_Json_Net() var serializer = new JsonNetSerializer(); var encoder = new JwtEncoder(algorithm, serializer, urlEncoder); - var actual = encoder.Encode(toEncode, key); + var actual = encoder.Encode(customer, key); actual.Should() .Be(expected, "because the same data encoded with the same key must result in the same token"); @@ -110,5 +110,22 @@ public void Encode_Should_Encode_To_Token_Using_Json_Net() private static IJsonSerializer CreateSerializer() => new DefaultJsonSerializerFactory().Create(); + + [TestMethod] + public void Encode_With_NoAlgorithm_Should_Encode_To_Token_Not_Needing_Secret() + { + var customer = TestData.Customer; + const string expected = TestData.TokenWithoutSignature; + + var algorithm = new NoneAlgorithm(); + var urlEncoder = new JwtBase64UrlEncoder(); + var serializer = CreateSerializer(); + var encoder = new JwtEncoder(algorithm, serializer, urlEncoder); + + var actual = encoder.Encode(customer, (string)null); + + actual.Should() + .Be(expected, "because the same data encoded with the same key must result in the same token"); + } } }