diff --git a/src/Microsoft.AspNetCore.Antiforgery/Internal/AntiforgeryLoggerExtensions.cs b/src/Microsoft.AspNetCore.Antiforgery/Internal/AntiforgeryLoggerExtensions.cs index aae0b3176e..5e115bb76a 100644 --- a/src/Microsoft.AspNetCore.Antiforgery/Internal/AntiforgeryLoggerExtensions.cs +++ b/src/Microsoft.AspNetCore.Antiforgery/Internal/AntiforgeryLoggerExtensions.cs @@ -14,6 +14,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal private static readonly Action _missingRequestToken; private static readonly Action _newCookieToken; private static readonly Action _reusedCookieToken; + private static readonly Action _tokenDeserializeException; static AntiforgeryLoggerExtensions() { @@ -42,6 +43,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal LogLevel.Debug, 6, "An antiforgery cookie token was reused."); + _tokenDeserializeException = LoggerMessage.Define( + LogLevel.Error, + 7, + "An exception was thrown while deserializing the token."); } public static void ValidationFailed(this ILogger logger, string message) @@ -73,5 +78,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal { _reusedCookieToken(logger, null); } + + public static void TokenDeserializeException(this ILogger logger, Exception exception) + { + _tokenDeserializeException(logger, exception); + } } } diff --git a/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgery.cs b/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgery.cs index 44310c5187..eeb92cf777 100644 --- a/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgery.cs +++ b/src/Microsoft.AspNetCore.Antiforgery/Internal/DefaultAntiforgery.cs @@ -5,7 +5,6 @@ using System; using System.Diagnostics; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -329,15 +328,20 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal try { var serializedToken = _tokenStore.GetCookieToken(httpContext); - var token = _tokenSerializer.Deserialize(serializedToken); - return token; + if (serializedToken != null) + { + var token = _tokenSerializer.Deserialize(serializedToken); + return token; + } } - catch + catch (Exception ex) { // ignore failures since we'll just generate a new token - return null; + _logger.TokenDeserializeException(ex); } + + return null; } private IAntiforgeryFeature GetTokensInternal(HttpContext httpContext) diff --git a/test/Microsoft.AspNetCore.Antiforgery.Test/Internal/DefaultAntiforgeryTest.cs b/test/Microsoft.AspNetCore.Antiforgery.Test/Internal/DefaultAntiforgeryTest.cs index 335f2c91a2..09de9243d5 100644 --- a/test/Microsoft.AspNetCore.Antiforgery.Test/Internal/DefaultAntiforgeryTest.cs +++ b/test/Microsoft.AspNetCore.Antiforgery.Test/Internal/DefaultAntiforgeryTest.cs @@ -928,6 +928,43 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal Times.Never); } + [Fact] + public void SetCookieTokenAndHeader_NullCookieToken() + { + // Arrange + var antiforgeryFeature = new AntiforgeryFeature + { + HaveDeserializedCookieToken = false, + HaveGeneratedNewCookieToken = false, + HaveStoredNewCookieToken = true, + NewCookieToken = new AntiforgeryToken(), + NewCookieTokenString = "serialized-cookie-token-from-context", + NewRequestToken = new AntiforgeryToken(), + NewRequestTokenString = "serialized-form-token-from-context", + }; + var context = CreateMockContext( + new AntiforgeryOptions(), + useOldCookie: false, + isOldCookieValid: false, + antiforgeryFeature: antiforgeryFeature); + var testTokenSet = new TestTokenSet + { + OldCookieTokenString = null + }; + + var nullTokenStore = GetTokenStore(context.HttpContext, testTokenSet, false); + var antiforgery = GetAntiforgery( + context.HttpContext, + tokenGenerator: context.TokenGenerator.Object, + tokenStore: nullTokenStore.Object); + + // Act + antiforgery.SetCookieTokenAndHeader(context.HttpContext); + + // Assert + context.TokenSerializer.Verify(s => s.Deserialize(null), Times.Never); + } + private DefaultAntiforgery GetAntiforgery( HttpContext httpContext, AntiforgeryOptions options = null, @@ -1053,7 +1090,9 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal mockGenerator .Setup(o => o.GenerateCookieToken()) .Returns(useOldCookie ? testTokenSet.OldCookieToken : testTokenSet.NewCookieToken); - + mockGenerator + .Setup(o => o.IsCookieTokenValid(null)) + .Returns(false); mockGenerator .Setup(o => o.IsCookieTokenValid(testTokenSet.OldCookieToken)) .Returns(isOldCookieValid);