diff --git a/src/Microsoft.AspNetCore.Antiforgery/AntiforgeryValidationException.cs b/src/Microsoft.AspNetCore.Antiforgery/AntiforgeryValidationException.cs
index b2fb6e9618..f1ade05d34 100644
--- a/src/Microsoft.AspNetCore.Antiforgery/AntiforgeryValidationException.cs
+++ b/src/Microsoft.AspNetCore.Antiforgery/AntiforgeryValidationException.cs
@@ -12,12 +12,23 @@ namespace Microsoft.AspNetCore.Antiforgery
{
///
/// Creates a new instance of with the specified
- /// exception .
+ /// exception message.
///
/// The message that describes the error.
public AntiforgeryValidationException(string message)
: base(message)
{
}
+
+ ///
+ /// Creates a new instance of with the specified
+ /// exception message and inner exception.
+ ///
+ /// The message that describes the error.
+ /// The inner .
+ public AntiforgeryValidationException(string message, Exception innerException)
+ : base(message, innerException)
+ {
+ }
}
}
diff --git a/src/Microsoft.AspNetCore.Antiforgery/Internal/AntiforgeryLoggerExtensions.cs b/src/Microsoft.AspNetCore.Antiforgery/Internal/AntiforgeryLoggerExtensions.cs
index 0c8ef5ccfd..232279e4be 100644
--- a/src/Microsoft.AspNetCore.Antiforgery/Internal/AntiforgeryLoggerExtensions.cs
+++ b/src/Microsoft.AspNetCore.Antiforgery/Internal/AntiforgeryLoggerExtensions.cs
@@ -8,6 +8,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
{
internal static class AntiforgeryLoggerExtensions
{
+ private static readonly Action _failedToDeserialzeTokens;
private static readonly Action _validationFailed;
private static readonly Action _validated;
private static readonly Action _missingCookieToken;
@@ -54,6 +55,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
"The 'Cache-Control' and 'Pragma' headers have been overridden and set to 'no-cache, no-store' and " +
"'no-cache' respectively to prevent caching of this response. Any response that uses antiforgery " +
"should not be cached.");
+ _failedToDeserialzeTokens = LoggerMessage.Define(
+ LogLevel.Debug,
+ 9,
+ "Failed to deserialize antiforgery tokens.");
}
public static void ValidationFailed(this ILogger logger, string message)
@@ -95,5 +100,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
{
_responseCacheHeadersOverridenToNoCache(logger, null);
}
+
+ public static void FailedToDeserialzeTokens(this ILogger logger, Exception exception)
+ {
+ _failedToDeserialzeTokens(logger, exception);
+ }
}
}
diff --git a/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgery.cs b/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgery.cs
index ae28906069..24aa3cb7d3 100644
--- a/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgery.cs
+++ b/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgery.cs
@@ -124,7 +124,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
// Extract cookie & request tokens
AntiforgeryToken deserializedCookieToken;
AntiforgeryToken deserializedRequestToken;
- DeserializeTokens(httpContext, tokens, out deserializedCookieToken, out deserializedRequestToken);
+ if (!TryDeserializeTokens(httpContext, tokens, out deserializedCookieToken, out deserializedRequestToken))
+ {
+ return false;
+ }
// Validate
string message;
@@ -197,6 +200,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
// Extract cookie & request tokens
AntiforgeryToken deserializedCookieToken;
AntiforgeryToken deserializedRequestToken;
+
DeserializeTokens(
httpContext,
antiforgeryTokenSet,
@@ -430,6 +434,27 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
_options.HeaderName);
}
+ private bool TryDeserializeTokens(
+ HttpContext httpContext,
+ AntiforgeryTokenSet antiforgeryTokenSet,
+ out AntiforgeryToken cookieToken,
+ out AntiforgeryToken requestToken)
+ {
+ try
+ {
+ DeserializeTokens(httpContext, antiforgeryTokenSet, out cookieToken, out requestToken);
+ return true;
+ }
+ catch (AntiforgeryValidationException ex)
+ {
+ _logger.FailedToDeserialzeTokens(ex);
+
+ cookieToken = null;
+ requestToken = null;
+ return false;
+ }
+ }
+
private void DeserializeTokens(
HttpContext httpContext,
AntiforgeryTokenSet antiforgeryTokenSet,
diff --git a/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgeryTokenSerializer.cs b/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgeryTokenSerializer.cs
index 474b2fd7a9..d71f2a2185 100644
--- a/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgeryTokenSerializer.cs
+++ b/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgeryTokenSerializer.cs
@@ -75,7 +75,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
}
// if we reached this point, something went wrong deserializing
- throw new InvalidOperationException(Resources.AntiforgeryToken_DeserializationFailed, innerException);
+ throw new AntiforgeryValidationException(Resources.AntiforgeryToken_DeserializationFailed, innerException);
}
/* The serialized format of the anti-XSRF token is as follows:
diff --git a/test/Microsoft.AspNetCore.Antiforgery.Test/Internal/DefaultAntiforgeryTokenSerializerTest.cs b/test/Microsoft.AspNetCore.Antiforgery.Test/Internal/DefaultAntiforgeryTokenSerializerTest.cs
index 80280de4f3..88ce09b4e2 100644
--- a/test/Microsoft.AspNetCore.Antiforgery.Test/Internal/DefaultAntiforgeryTokenSerializerTest.cs
+++ b/test/Microsoft.AspNetCore.Antiforgery.Test/Internal/DefaultAntiforgeryTokenSerializerTest.cs
@@ -51,7 +51,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
var testSerializer = new DefaultAntiforgeryTokenSerializer(_dataProtector.Object, _pool);
// Act & assert
- var ex = Assert.Throws(() => testSerializer.Deserialize(serializedToken));
+ var ex = Assert.Throws(() => testSerializer.Deserialize(serializedToken));
Assert.Equal(@"The antiforgery token could not be decrypted.", ex.Message);
}