diff --git a/src/JsonWebToken/JwtReader.cs b/src/JsonWebToken/JwtReader.cs
index f81b914d8..ced7aabd2 100644
--- a/src/JsonWebToken/JwtReader.cs
+++ b/src/JsonWebToken/JwtReader.cs
@@ -346,7 +346,7 @@ private TokenValidationResult TryReadJwe(
}
else
{
- if (decryptionResult.Status == TokenValidationStatus.MalformedToken)
+ if (decryptionResult.Status == TokenValidationStatus.MalformedToken && !policy.HasValidation)
{
// The decrypted payload is not a nested JWT
jwe = new Jwt(header, compressed ? decompressedBytes.ToArray() : decryptedBytes.ToArray(), decryptionKey);
diff --git a/src/JsonWebToken/SignatureValidationPolicy.cs b/src/JsonWebToken/SignatureValidationPolicy.cs
index cd01f70ec..ba9046093 100644
--- a/src/JsonWebToken/SignatureValidationPolicy.cs
+++ b/src/JsonWebToken/SignatureValidationPolicy.cs
@@ -22,6 +22,11 @@ public abstract class SignatureValidationPolicy
/// Allows to ignore the signature, whatever ther is an algorithm defined or not.
///
public static readonly SignatureValidationPolicy IgnoreSignature = new IgnoreSignatureValidationContext();
+
+ ///
+ /// Gets whether the signature validation is enabled.
+ ///
+ public abstract bool IsEnabled { get; }
///
/// Try to validate the token signature.
@@ -58,6 +63,9 @@ public DefaultSignatureValidationPolicy(IKeyProvider keyProvider, SignatureAlgor
_algorithm = algorithm;
}
+ ///
+ public override bool IsEnabled => true;
+
public override SignatureValidationResult TryValidateSignature(JwtHeader header, ReadOnlySpan contentBytes, ReadOnlySpan signatureSegment)
{
if (contentBytes.IsEmpty && signatureSegment.IsEmpty)
@@ -122,6 +130,9 @@ public override SignatureValidationResult TryValidateSignature(JwtHeader header,
private sealed class NoSignatureValidationContext : SignatureValidationPolicy
{
+ ///
+ public override bool IsEnabled => true;
+
public override SignatureValidationResult TryValidateSignature(JwtHeader header, ReadOnlySpan contentBytes, ReadOnlySpan signatureSegment)
{
return (contentBytes.Length == 0 && signatureSegment.Length == 0) || (signatureSegment.IsEmpty && header.SignatureAlgorithm == SignatureAlgorithm.None)
@@ -132,6 +143,9 @@ public override SignatureValidationResult TryValidateSignature(JwtHeader header,
private sealed class IgnoreSignatureValidationContext : SignatureValidationPolicy
{
+ ///
+ public override bool IsEnabled => false;
+
public override SignatureValidationResult TryValidateSignature(JwtHeader header, ReadOnlySpan contentBytes, ReadOnlySpan signatureSegment)
{
return SignatureValidationResult.Success();
diff --git a/src/JsonWebToken/TokenValidationPolicy.cs b/src/JsonWebToken/TokenValidationPolicy.cs
index eab4ea2d3..6fa7ec095 100644
--- a/src/JsonWebToken/TokenValidationPolicy.cs
+++ b/src/JsonWebToken/TokenValidationPolicy.cs
@@ -80,7 +80,7 @@ internal TokenValidationPolicy(
///
/// Gets whether the has validation.
///
- public bool HasValidation => _validators.Length != 0;
+ public bool HasValidation => _control != 0 || _validators.Length != 0 || SignatureValidationPolicy.IsEnabled;
///
/// Gets whether the issuer 'iss' is required.
diff --git a/src/JsonWebToken/TokenValidationPolicyBuilder.cs b/src/JsonWebToken/TokenValidationPolicyBuilder.cs
index 0eb31b8b0..b7a2ae5ae 100644
--- a/src/JsonWebToken/TokenValidationPolicyBuilder.cs
+++ b/src/JsonWebToken/TokenValidationPolicyBuilder.cs
@@ -171,7 +171,7 @@ public TokenValidationPolicyBuilder RequireSignature(Jwk key)
throw new InvalidOperationException($"The key does not define an 'alg' parameter. Use the method {nameof(RequireSignature)} with a {nameof(Jwk)} and a {nameof(SignatureAlgorithm)}.");
}
- return RequireSignature(key, null);
+ return RequireSignature(key, (SignatureAlgorithm?)null);
}
///
@@ -180,7 +180,29 @@ public TokenValidationPolicyBuilder RequireSignature(Jwk key)
///
///
///
- public TokenValidationPolicyBuilder RequireSignature(Jwk key, SignatureAlgorithm? algorithm) => RequireSignature(new Jwks(key), algorithm);
+ public TokenValidationPolicyBuilder RequireSignature(Jwk key, SignatureAlgorithm? algorithm)
+ => RequireSignature(new Jwks(key), algorithm);
+
+ ///
+ /// Requires a valid signature.
+ ///
+ ///
+ ///
+ ///
+ public TokenValidationPolicyBuilder RequireSignature(Jwk key, string? algorithm)
+ {
+ if (algorithm is null)
+ {
+ throw new ArgumentNullException(nameof(algorithm));
+ }
+
+ if (!SignatureAlgorithm.TryParse(Utf8.GetBytes(algorithm), out var alg))
+ {
+ throw new NotSupportedException($"The algorithm '{alg}' is not supported.");
+ }
+
+ return RequireSignature(new Jwks(key), alg);
+ }
///
/// Requires a valid signature.
@@ -210,7 +232,8 @@ public TokenValidationPolicyBuilder RequireSignature(Jwk key)
///
///
///
- public TokenValidationPolicyBuilder RequireSignature(Jwks keySet, SignatureAlgorithm? algorithm) => RequireSignature(new StaticKeyProvider(keySet), algorithm);
+ public TokenValidationPolicyBuilder RequireSignature(Jwks keySet, SignatureAlgorithm? algorithm)
+ => RequireSignature(new StaticKeyProvider(keySet), algorithm);
///
/// Requires a valid signature.
diff --git a/test/JsonWebToken.Tests/JsonWebTokenReaderTests.cs b/test/JsonWebToken.Tests/JsonWebTokenReaderTests.cs
index b5e450057..93f2887a9 100644
--- a/test/JsonWebToken.Tests/JsonWebTokenReaderTests.cs
+++ b/test/JsonWebToken.Tests/JsonWebTokenReaderTests.cs
@@ -191,6 +191,49 @@ public void ReadJwt_CriticalHeader(string jwt, TokenValidationStatus expected)
Assert.Equal(expected, result.Status);
}
+ [Theory]
+ [InlineData("eyJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiQTEyOEtXIn0.4VETXwjtEQIHzctz2FTAef8iHvk8ShfMJrRvDNVISdUh9Zju4tl75w.o0IVPs65CR8B0b6fxH3mow.p8DIesdqyemto-EKiHSA19jiobfS6sR4kfe4PGEyruI.VtIn9WFytiZNjP7wXBeNNg")]
+ public void Issue504_Valid(string jwt)
+ {
+ var reader = new JwtReader(new SymmetricJwk("R9MyWaEoyiMYViVWo8Fk4T"));
+ var policy = new TokenValidationPolicyBuilder()
+ .IgnoreSignature()
+ .Build();
+
+ var result = reader.TryReadToken(jwt, policy);
+ Assert.Equal(TokenValidationStatus.Success, result.Status);
+ }
+
+ [Theory]
+ [InlineData("eyJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiQTEyOEtXIn0.4VETXwjtEQIHzctz2FTAef8iHvk8ShfMJrRvDNVISdUh9Zju4tl75w.o0IVPs65CR8B0b6fxH3mow.p8DIesdqyemto-EKiHSA19jiobfS6sR4kfe4PGEyruI.VtIn9WFytiZNjP7wXBeNNg", true, false, false)]
+ [InlineData("eyJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiQTEyOEtXIn0.4VETXwjtEQIHzctz2FTAef8iHvk8ShfMJrRvDNVISdUh9Zju4tl75w.o0IVPs65CR8B0b6fxH3mow.p8DIesdqyemto-EKiHSA19jiobfS6sR4kfe4PGEyruI.VtIn9WFytiZNjP7wXBeNNg", false, true, false)]
+ [InlineData("eyJlbmMiOiJBMTI4Q0JDLUhTMjU2IiwiYWxnIjoiQTEyOEtXIn0.4VETXwjtEQIHzctz2FTAef8iHvk8ShfMJrRvDNVISdUh9Zju4tl75w.o0IVPs65CR8B0b6fxH3mow.p8DIesdqyemto-EKiHSA19jiobfS6sR4kfe4PGEyruI.VtIn9WFytiZNjP7wXBeNNg", false, false, true)]
+ public void Issue504_Invalid(string jwt, bool requireAudience, bool requireSignature, bool requireOther)
+ {
+ var reader = new JwtReader(new SymmetricJwk("R9MyWaEoyiMYViVWo8Fk4T"));
+ var builder = new TokenValidationPolicyBuilder();
+ if (requireAudience)
+ {
+ builder.RequireAudience("test");
+ }
+ if (requireSignature)
+ {
+ builder.RequireSignature(SymmetricJwk.FromBase64Url("R9MyWaEoyiMYViVWo8Fk4TUGWiSoaW6U1nOqXri8_XU"), "HS256");
+ }
+ else
+ {
+ builder.IgnoreSignature();
+ }
+ if (requireOther)
+ {
+ builder.AddValidator(new FakeValidator());
+ }
+
+ var policy = builder.Build();
+ var result = reader.TryReadToken(jwt, policy);
+ Assert.Equal(TokenValidationStatus.MalformedToken, result.Status);
+ }
+
[Theory]
[InlineData("eyJhbGciOiJub25lIn0.eyJleHAiOjk5MDAwMDAwMDAsIm5iZiI6MTUwMDAwMDAwMH0.")]
[InlineData("eyJhbGciOiJub25lIn0.eyJleHAiOjk5MDAwMDAwMDB9.")]
@@ -238,7 +281,7 @@ public void Issue489_NoValidation_Valid(string jwt)
.Build();
var result = reader.TryReadToken(jwt, policy);
- Assert.Equal(TokenValidationStatus.Success , result.Status);
+ Assert.Equal(TokenValidationStatus.Success, result.Status);
}
private HttpResponseMessage BackchannelRequestToken(HttpRequestMessage req)
@@ -325,4 +368,12 @@ public bool TryHandle(JwtHeader heade, string headerName)
return _value;
}
}
+
+ internal class FakeValidator : IValidator
+ {
+ public TokenValidationResult TryValidate(Jwt jwt)
+ {
+ return TokenValidationResult.MalformedToken();
+ }
+ }
}
\ No newline at end of file