Make IAntiforgeryContextAccessor a Feature

This commit is contained in:
ryanbrandenburg 2016-03-23 11:19:34 -07:00
parent c237f8989a
commit 94cefde3ec
7 changed files with 233 additions and 250 deletions

View File

@ -6,7 +6,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
/// <summary> /// <summary>
/// Used to hold per-request state. /// Used to hold per-request state.
/// </summary> /// </summary>
public class AntiforgeryContext public class AntiforgeryFeature : IAntiforgeryFeature
{ {
public bool HaveDeserializedCookieToken { get; set; } public bool HaveDeserializedCookieToken { get; set; }

View File

@ -48,18 +48,18 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
CheckSSLConfig(httpContext); CheckSSLConfig(httpContext);
var antiforgeryContext = GetTokensInternal(httpContext); var antiforgeryFeature = GetTokensInternal(httpContext);
var tokenSet = Serialize(antiforgeryContext); var tokenSet = Serialize(antiforgeryFeature);
if (!antiforgeryContext.HaveStoredNewCookieToken) if (!antiforgeryFeature.HaveStoredNewCookieToken)
{ {
if (antiforgeryContext.NewCookieToken != null) if (antiforgeryFeature.NewCookieToken != null)
{ {
// Serialize handles the new cookie token string. // Serialize handles the new cookie token string.
Debug.Assert(antiforgeryContext.NewCookieTokenString != null); Debug.Assert(antiforgeryFeature.NewCookieTokenString != null);
SaveCookieTokenAndHeader(httpContext, antiforgeryContext.NewCookieTokenString); SaveCookieTokenAndHeader(httpContext, antiforgeryFeature.NewCookieTokenString);
antiforgeryContext.HaveStoredNewCookieToken = true; antiforgeryFeature.HaveStoredNewCookieToken = true;
_logger.NewCookieToken(); _logger.NewCookieToken();
} }
else else
@ -81,8 +81,8 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
CheckSSLConfig(httpContext); CheckSSLConfig(httpContext);
var antiforgeryContext = GetTokensInternal(httpContext); var antiforgeryFeature = GetTokensInternal(httpContext);
return Serialize(antiforgeryContext); return Serialize(antiforgeryFeature);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -263,17 +263,17 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
CheckSSLConfig(httpContext); CheckSSLConfig(httpContext);
var antiforgeryContext = GetCookieTokens(httpContext); var antiforgeryFeature = GetCookieTokens(httpContext);
if (!antiforgeryContext.HaveStoredNewCookieToken && antiforgeryContext.NewCookieToken != null) if (!antiforgeryFeature.HaveStoredNewCookieToken && antiforgeryFeature.NewCookieToken != null)
{ {
if (antiforgeryContext.NewCookieTokenString == null) if (antiforgeryFeature.NewCookieTokenString == null)
{ {
antiforgeryContext.NewCookieTokenString = antiforgeryFeature.NewCookieTokenString =
_tokenSerializer.Serialize(antiforgeryContext.NewCookieToken); _tokenSerializer.Serialize(antiforgeryFeature.NewCookieToken);
} }
SaveCookieTokenAndHeader(httpContext, antiforgeryContext.NewCookieTokenString); SaveCookieTokenAndHeader(httpContext, antiforgeryFeature.NewCookieTokenString);
antiforgeryContext.HaveStoredNewCookieToken = true; antiforgeryFeature.HaveStoredNewCookieToken = true;
_logger.NewCookieToken(); _logger.NewCookieToken();
} }
else else
@ -325,35 +325,41 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
return true; return true;
} }
private AntiforgeryContext GetCookieTokens(HttpContext httpContext) private static IAntiforgeryFeature GetAntiforgeryFeature(HttpContext httpContext)
{ {
var services = httpContext.RequestServices; var antiforgeryFeature = httpContext.Features.Get<IAntiforgeryFeature>();
var contextAccessor = services.GetRequiredService<IAntiforgeryContextAccessor>(); if (antiforgeryFeature == null)
if (contextAccessor.Value == null)
{ {
contextAccessor.Value = new AntiforgeryContext(); antiforgeryFeature = new AntiforgeryFeature();
httpContext.Features.Set(antiforgeryFeature);
} }
var antiforgeryContext = contextAccessor.Value; return antiforgeryFeature;
if (antiforgeryContext.HaveGeneratedNewCookieToken) }
private IAntiforgeryFeature GetCookieTokens(HttpContext httpContext)
{
var antiforgeryFeature = GetAntiforgeryFeature(httpContext);
if (antiforgeryFeature.HaveGeneratedNewCookieToken)
{ {
Debug.Assert(antiforgeryContext.HaveDeserializedCookieToken); Debug.Assert(antiforgeryFeature.HaveDeserializedCookieToken);
// Have executed this method earlier in the context of this request. // Have executed this method earlier in the context of this request.
return antiforgeryContext; return antiforgeryFeature;
} }
AntiforgeryToken cookieToken; AntiforgeryToken cookieToken;
if (antiforgeryContext.HaveDeserializedCookieToken) if (antiforgeryFeature.HaveDeserializedCookieToken)
{ {
cookieToken = antiforgeryContext.CookieToken; cookieToken = antiforgeryFeature.CookieToken;
} }
else else
{ {
cookieToken = GetCookieTokenDoesNotThrow(httpContext); cookieToken = GetCookieTokenDoesNotThrow(httpContext);
antiforgeryContext.CookieToken = cookieToken; antiforgeryFeature.CookieToken = cookieToken;
antiforgeryContext.HaveDeserializedCookieToken = true; antiforgeryFeature.HaveDeserializedCookieToken = true;
} }
AntiforgeryToken newCookieToken; AntiforgeryToken newCookieToken;
@ -369,10 +375,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Debug.Assert(_tokenGenerator.IsCookieTokenValid(newCookieToken)); Debug.Assert(_tokenGenerator.IsCookieTokenValid(newCookieToken));
} }
antiforgeryContext.HaveGeneratedNewCookieToken = true; antiforgeryFeature.HaveGeneratedNewCookieToken = true;
antiforgeryContext.NewCookieToken = newCookieToken; antiforgeryFeature.NewCookieToken = newCookieToken;
return antiforgeryContext; return antiforgeryFeature;
} }
private AntiforgeryToken GetCookieTokenDoesNotThrow(HttpContext httpContext) private AntiforgeryToken GetCookieTokenDoesNotThrow(HttpContext httpContext)
@ -391,42 +397,42 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
} }
} }
private AntiforgeryContext GetTokensInternal(HttpContext httpContext) private IAntiforgeryFeature GetTokensInternal(HttpContext httpContext)
{ {
var antiforgeryContext = GetCookieTokens(httpContext); var antiforgeryFeature = GetCookieTokens(httpContext);
if (antiforgeryContext.NewRequestToken == null) if (antiforgeryFeature.NewRequestToken == null)
{ {
var cookieToken = antiforgeryContext.NewCookieToken ?? antiforgeryContext.CookieToken; var cookieToken = antiforgeryFeature.NewCookieToken ?? antiforgeryFeature.CookieToken;
antiforgeryContext.NewRequestToken = _tokenGenerator.GenerateRequestToken( antiforgeryFeature.NewRequestToken = _tokenGenerator.GenerateRequestToken(
httpContext, httpContext,
httpContext.User, httpContext.User,
cookieToken); cookieToken);
} }
return antiforgeryContext; return antiforgeryFeature;
} }
private AntiforgeryTokenSet Serialize(AntiforgeryContext antiforgeryContext) private AntiforgeryTokenSet Serialize(IAntiforgeryFeature antiforgeryFeature)
{ {
// Should only be called after new tokens have been generated. // Should only be called after new tokens have been generated.
Debug.Assert(antiforgeryContext.HaveGeneratedNewCookieToken); Debug.Assert(antiforgeryFeature.HaveGeneratedNewCookieToken);
Debug.Assert(antiforgeryContext.NewRequestToken != null); Debug.Assert(antiforgeryFeature.NewRequestToken != null);
if (antiforgeryContext.NewRequestTokenString == null) if (antiforgeryFeature.NewRequestTokenString == null)
{ {
antiforgeryContext.NewRequestTokenString = antiforgeryFeature.NewRequestTokenString =
_tokenSerializer.Serialize(antiforgeryContext.NewRequestToken); _tokenSerializer.Serialize(antiforgeryFeature.NewRequestToken);
} }
if (antiforgeryContext.NewCookieTokenString == null && antiforgeryContext.NewCookieToken != null) if (antiforgeryFeature.NewCookieTokenString == null && antiforgeryFeature.NewCookieToken != null)
{ {
antiforgeryContext.NewCookieTokenString = antiforgeryFeature.NewCookieTokenString =
_tokenSerializer.Serialize(antiforgeryContext.NewCookieToken); _tokenSerializer.Serialize(antiforgeryFeature.NewCookieToken);
} }
return new AntiforgeryTokenSet( return new AntiforgeryTokenSet(
antiforgeryContext.NewRequestTokenString, antiforgeryFeature.NewRequestTokenString,
antiforgeryContext.NewCookieTokenString, antiforgeryFeature.NewCookieTokenString,
_options.FormFieldName, _options.FormFieldName,
_options.HeaderName); _options.HeaderName);
} }
@ -437,36 +443,30 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
out AntiforgeryToken cookieToken, out AntiforgeryToken cookieToken,
out AntiforgeryToken requestToken) out AntiforgeryToken requestToken)
{ {
var services = httpContext.RequestServices; var antiforgeryFeature = GetAntiforgeryFeature(httpContext);
var contextAccessor = services.GetRequiredService<IAntiforgeryContextAccessor>();
if (contextAccessor.Value == null)
{
contextAccessor.Value = new AntiforgeryContext();
}
var antiforgeryContext = contextAccessor.Value; if (antiforgeryFeature.HaveDeserializedCookieToken)
if (antiforgeryContext.HaveDeserializedCookieToken)
{ {
cookieToken = antiforgeryContext.CookieToken; cookieToken = antiforgeryFeature.CookieToken;
} }
else else
{ {
cookieToken = _tokenSerializer.Deserialize(antiforgeryTokenSet.CookieToken); cookieToken = _tokenSerializer.Deserialize(antiforgeryTokenSet.CookieToken);
antiforgeryContext.CookieToken = cookieToken; antiforgeryFeature.CookieToken = cookieToken;
antiforgeryContext.HaveDeserializedCookieToken = true; antiforgeryFeature.HaveDeserializedCookieToken = true;
} }
if (antiforgeryContext.HaveDeserializedRequestToken) if (antiforgeryFeature.HaveDeserializedRequestToken)
{ {
requestToken = antiforgeryContext.RequestToken; requestToken = antiforgeryFeature.RequestToken;
} }
else else
{ {
requestToken = _tokenSerializer.Deserialize(antiforgeryTokenSet.RequestToken); requestToken = _tokenSerializer.Deserialize(antiforgeryTokenSet.RequestToken);
antiforgeryContext.RequestToken = requestToken; antiforgeryFeature.RequestToken = requestToken;
antiforgeryContext.HaveDeserializedRequestToken = true; antiforgeryFeature.HaveDeserializedRequestToken = true;
} }
} }
} }

View File

@ -1,10 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Antiforgery.Internal
{
public class DefaultAntiforgeryContextAccessor : IAntiforgeryContextAccessor
{
public AntiforgeryContext Value { get; set; }
}
}

View File

@ -1,10 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Antiforgery.Internal
{
public interface IAntiforgeryContextAccessor
{
AntiforgeryContext Value { get; set; }
}
}

View File

@ -0,0 +1,25 @@
namespace Microsoft.AspNetCore.Antiforgery.Internal
{
public interface IAntiforgeryFeature
{
AntiforgeryToken CookieToken { get; set; }
bool HaveDeserializedCookieToken { get; set; }
bool HaveDeserializedRequestToken { get; set; }
bool HaveGeneratedNewCookieToken { get; set; }
bool HaveStoredNewCookieToken { get; set; }
AntiforgeryToken NewCookieToken { get; set; }
string NewCookieTokenString { get; set; }
AntiforgeryToken NewRequestToken { get; set; }
string NewRequestTokenString { get; set; }
AntiforgeryToken RequestToken { get; set; }
}
}

View File

@ -37,7 +37,6 @@ namespace Microsoft.Extensions.DependencyInjection
services.TryAddSingleton<IAntiforgeryTokenSerializer, DefaultAntiforgeryTokenSerializer>(); services.TryAddSingleton<IAntiforgeryTokenSerializer, DefaultAntiforgeryTokenSerializer>();
services.TryAddSingleton<IAntiforgeryTokenStore, DefaultAntiforgeryTokenStore>(); services.TryAddSingleton<IAntiforgeryTokenStore, DefaultAntiforgeryTokenStore>();
services.TryAddSingleton<IClaimUidExtractor, DefaultClaimUidExtractor>(); services.TryAddSingleton<IClaimUidExtractor, DefaultClaimUidExtractor>();
services.TryAddScoped<IAntiforgeryContextAccessor, DefaultAntiforgeryContextAccessor>();
services.TryAddSingleton<IAntiforgeryAdditionalDataProvider, DefaultAntiforgeryAdditionalDataProvider>(); services.TryAddSingleton<IAntiforgeryAdditionalDataProvider, DefaultAntiforgeryAdditionalDataProvider>();
services.TryAddSingleton<ObjectPoolProvider>(new DefaultObjectPoolProvider()); services.TryAddSingleton<ObjectPoolProvider>(new DefaultObjectPoolProvider());

View File

@ -5,6 +5,7 @@ using System;
using System.Security.Claims; using System.Security.Claims;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Http.Internal; using Microsoft.AspNetCore.Http.Internal;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@ -181,13 +182,13 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
public void GetTokens_ExistingInvalidCookieToken_GeneratesANewCookieTokenAndANewFormToken() public void GetTokens_ExistingInvalidCookieToken_GeneratesANewCookieTokenAndANewFormToken()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor(); var antiforgeryFeature = new AntiforgeryFeature();
// Generate a new cookie. // Generate a new cookie.
var context = CreateMockContext( var context = CreateMockContext(
new AntiforgeryOptions(), new AntiforgeryOptions(),
useOldCookie: false, useOldCookie: false,
isOldCookieValid: false, isOldCookieValid: false,
contextAccessor: contextAccessor); antiforgeryFeature: antiforgeryFeature);
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
// Act // Act
@ -197,14 +198,14 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.Equal(context.TestTokenSet.NewCookieTokenString, tokenset.CookieToken); Assert.Equal(context.TestTokenSet.NewCookieTokenString, tokenset.CookieToken);
Assert.Equal(context.TestTokenSet.FormTokenString, tokenset.RequestToken); Assert.Equal(context.TestTokenSet.FormTokenString, tokenset.RequestToken);
Assert.NotNull(contextAccessor.Value); Assert.NotNull(antiforgeryFeature);
Assert.True(contextAccessor.Value.HaveDeserializedCookieToken); Assert.True(antiforgeryFeature.HaveDeserializedCookieToken);
Assert.Equal(context.TestTokenSet.OldCookieToken, contextAccessor.Value.CookieToken); Assert.Equal(context.TestTokenSet.OldCookieToken, antiforgeryFeature.CookieToken);
Assert.True(contextAccessor.Value.HaveGeneratedNewCookieToken); Assert.True(antiforgeryFeature.HaveGeneratedNewCookieToken);
Assert.Equal(context.TestTokenSet.NewCookieToken, contextAccessor.Value.NewCookieToken); Assert.Equal(context.TestTokenSet.NewCookieToken, antiforgeryFeature.NewCookieToken);
Assert.Equal(context.TestTokenSet.NewCookieTokenString, contextAccessor.Value.NewCookieTokenString); Assert.Equal(context.TestTokenSet.NewCookieTokenString, antiforgeryFeature.NewCookieTokenString);
Assert.Equal(context.TestTokenSet.RequestToken, contextAccessor.Value.NewRequestToken); Assert.Equal(context.TestTokenSet.RequestToken, antiforgeryFeature.NewRequestToken);
Assert.Equal(context.TestTokenSet.FormTokenString, contextAccessor.Value.NewRequestTokenString); Assert.Equal(context.TestTokenSet.FormTokenString, antiforgeryFeature.NewRequestTokenString);
} }
[Fact] [Fact]
@ -239,12 +240,12 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
public void GetTokens_ExistingValidCookieToken_GeneratesANewFormToken() public void GetTokens_ExistingValidCookieToken_GeneratesANewFormToken()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor(); var antiforgeryFeature = new AntiforgeryFeature();
var context = CreateMockContext( var context = CreateMockContext(
new AntiforgeryOptions(), new AntiforgeryOptions(),
useOldCookie: true, useOldCookie: true,
isOldCookieValid: true, isOldCookieValid: true,
contextAccessor: contextAccessor); antiforgeryFeature: antiforgeryFeature);
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
// Act // Act
@ -254,34 +255,31 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.Null(tokenset.CookieToken); Assert.Null(tokenset.CookieToken);
Assert.Equal(context.TestTokenSet.FormTokenString, tokenset.RequestToken); Assert.Equal(context.TestTokenSet.FormTokenString, tokenset.RequestToken);
Assert.NotNull(contextAccessor.Value); Assert.NotNull(antiforgeryFeature);
Assert.True(contextAccessor.Value.HaveDeserializedCookieToken); Assert.True(antiforgeryFeature.HaveDeserializedCookieToken);
Assert.Equal(context.TestTokenSet.OldCookieToken, contextAccessor.Value.CookieToken); Assert.Equal(context.TestTokenSet.OldCookieToken, antiforgeryFeature.CookieToken);
Assert.True(contextAccessor.Value.HaveGeneratedNewCookieToken); Assert.True(antiforgeryFeature.HaveGeneratedNewCookieToken);
Assert.Null(contextAccessor.Value.NewCookieToken); Assert.Null(antiforgeryFeature.NewCookieToken);
Assert.Equal(context.TestTokenSet.RequestToken, contextAccessor.Value.NewRequestToken); Assert.Equal(context.TestTokenSet.RequestToken, antiforgeryFeature.NewRequestToken);
Assert.Equal(context.TestTokenSet.FormTokenString, contextAccessor.Value.NewRequestTokenString); Assert.Equal(context.TestTokenSet.FormTokenString, antiforgeryFeature.NewRequestTokenString);
} }
[Fact] [Fact]
public void GetTokens_DoesNotSerializeTwice() public void GetTokens_DoesNotSerializeTwice()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor var antiforgeryFeature = new AntiforgeryFeature
{ {
Value = new AntiforgeryContext HaveDeserializedCookieToken = true,
{ HaveGeneratedNewCookieToken = true,
HaveDeserializedCookieToken = true, NewRequestToken = new AntiforgeryToken(),
HaveGeneratedNewCookieToken = true, NewRequestTokenString = "serialized-form-token-from-context",
NewRequestToken = new AntiforgeryToken(),
NewRequestTokenString = "serialized-form-token-from-context",
},
}; };
var context = CreateMockContext( var context = CreateMockContext(
new AntiforgeryOptions(), new AntiforgeryOptions(),
useOldCookie: true, useOldCookie: true,
isOldCookieValid: true, isOldCookieValid: true,
contextAccessor: contextAccessor); antiforgeryFeature: antiforgeryFeature);
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
@ -292,7 +290,7 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.Null(tokenset.CookieToken); Assert.Null(tokenset.CookieToken);
Assert.Equal("serialized-form-token-from-context", tokenset.RequestToken); Assert.Equal("serialized-form-token-from-context", tokenset.RequestToken);
Assert.Null(contextAccessor.Value.NewCookieToken); Assert.Null(antiforgeryFeature.NewCookieToken);
// Token serializer not used. // Token serializer not used.
context.TokenSerializer.Verify( context.TokenSerializer.Verify(
@ -307,12 +305,12 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
public void GetAndStoreTokens_ExistingValidCookieToken_NotOverriden() public void GetAndStoreTokens_ExistingValidCookieToken_NotOverriden()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor(); var antiforgeryFeature = new AntiforgeryFeature();
var context = CreateMockContext( var context = CreateMockContext(
new AntiforgeryOptions(), new AntiforgeryOptions(),
useOldCookie: true, useOldCookie: true,
isOldCookieValid: true, isOldCookieValid: true,
contextAccessor: contextAccessor); antiforgeryFeature: antiforgeryFeature);
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
// Act // Act
@ -327,25 +325,25 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.Null(tokenSet.CookieToken); Assert.Null(tokenSet.CookieToken);
Assert.Equal(context.TestTokenSet.FormTokenString, tokenSet.RequestToken); Assert.Equal(context.TestTokenSet.FormTokenString, tokenSet.RequestToken);
Assert.NotNull(contextAccessor.Value); Assert.NotNull(antiforgeryFeature);
Assert.True(contextAccessor.Value.HaveDeserializedCookieToken); Assert.True(antiforgeryFeature.HaveDeserializedCookieToken);
Assert.Equal(context.TestTokenSet.OldCookieToken, contextAccessor.Value.CookieToken); Assert.Equal(context.TestTokenSet.OldCookieToken, antiforgeryFeature.CookieToken);
Assert.True(contextAccessor.Value.HaveGeneratedNewCookieToken); Assert.True(antiforgeryFeature.HaveGeneratedNewCookieToken);
Assert.Null(contextAccessor.Value.NewCookieToken); Assert.Null(antiforgeryFeature.NewCookieToken);
Assert.Equal(context.TestTokenSet.RequestToken, contextAccessor.Value.NewRequestToken); Assert.Equal(context.TestTokenSet.RequestToken, antiforgeryFeature.NewRequestToken);
Assert.Equal(context.TestTokenSet.FormTokenString, contextAccessor.Value.NewRequestTokenString); Assert.Equal(context.TestTokenSet.FormTokenString, antiforgeryFeature.NewRequestTokenString);
} }
[Fact] [Fact]
public void GetAndStoreTokens_NoExistingCookieToken_Saved() public void GetAndStoreTokens_NoExistingCookieToken_Saved()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor(); var antiforgeryFeature = new AntiforgeryFeature();
var context = CreateMockContext( var context = CreateMockContext(
new AntiforgeryOptions(), new AntiforgeryOptions(),
useOldCookie: false, useOldCookie: false,
isOldCookieValid: false, isOldCookieValid: false,
contextAccessor: contextAccessor); antiforgeryFeature: antiforgeryFeature);
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
// Act // Act
@ -359,38 +357,35 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.Equal(context.TestTokenSet.NewCookieTokenString, tokenSet.CookieToken); Assert.Equal(context.TestTokenSet.NewCookieTokenString, tokenSet.CookieToken);
Assert.Equal(context.TestTokenSet.FormTokenString, tokenSet.RequestToken); Assert.Equal(context.TestTokenSet.FormTokenString, tokenSet.RequestToken);
Assert.NotNull(contextAccessor.Value); Assert.NotNull(antiforgeryFeature);
Assert.True(contextAccessor.Value.HaveDeserializedCookieToken); Assert.True(antiforgeryFeature.HaveDeserializedCookieToken);
Assert.Equal(context.TestTokenSet.OldCookieToken, contextAccessor.Value.CookieToken); Assert.Equal(context.TestTokenSet.OldCookieToken, antiforgeryFeature.CookieToken);
Assert.True(contextAccessor.Value.HaveGeneratedNewCookieToken); Assert.True(antiforgeryFeature.HaveGeneratedNewCookieToken);
Assert.Equal(context.TestTokenSet.NewCookieToken, contextAccessor.Value.NewCookieToken); Assert.Equal(context.TestTokenSet.NewCookieToken, antiforgeryFeature.NewCookieToken);
Assert.Equal(context.TestTokenSet.NewCookieTokenString, contextAccessor.Value.NewCookieTokenString); Assert.Equal(context.TestTokenSet.NewCookieTokenString, antiforgeryFeature.NewCookieTokenString);
Assert.Equal(context.TestTokenSet.RequestToken, contextAccessor.Value.NewRequestToken); Assert.Equal(context.TestTokenSet.RequestToken, antiforgeryFeature.NewRequestToken);
Assert.Equal(context.TestTokenSet.FormTokenString, contextAccessor.Value.NewRequestTokenString); Assert.Equal(context.TestTokenSet.FormTokenString, antiforgeryFeature.NewRequestTokenString);
Assert.True(contextAccessor.Value.HaveStoredNewCookieToken); Assert.True(antiforgeryFeature.HaveStoredNewCookieToken);
} }
[Fact] [Fact]
public void GetAndStoreTokens_DoesNotSerializeTwice() public void GetAndStoreTokens_DoesNotSerializeTwice()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor var antiforgeryFeature = new AntiforgeryFeature
{ {
Value = new AntiforgeryContext HaveDeserializedCookieToken = true,
{ HaveGeneratedNewCookieToken = true,
HaveDeserializedCookieToken = true, NewCookieToken = new AntiforgeryToken(),
HaveGeneratedNewCookieToken = true, NewCookieTokenString = "serialized-cookie-token-from-context",
NewCookieToken = new AntiforgeryToken(), NewRequestToken = new AntiforgeryToken(),
NewCookieTokenString = "serialized-cookie-token-from-context", NewRequestTokenString = "serialized-form-token-from-context",
NewRequestToken = new AntiforgeryToken(),
NewRequestTokenString = "serialized-form-token-from-context",
},
}; };
var context = CreateMockContext( var context = CreateMockContext(
new AntiforgeryOptions(), new AntiforgeryOptions(),
useOldCookie: true, useOldCookie: true,
isOldCookieValid: true, isOldCookieValid: true,
contextAccessor: contextAccessor); antiforgeryFeature: antiforgeryFeature);
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
context.TokenStore context.TokenStore
@ -418,31 +413,28 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.Equal("serialized-cookie-token-from-context", tokenset.CookieToken); Assert.Equal("serialized-cookie-token-from-context", tokenset.CookieToken);
Assert.Equal("serialized-form-token-from-context", tokenset.RequestToken); Assert.Equal("serialized-form-token-from-context", tokenset.RequestToken);
Assert.True(contextAccessor.Value.HaveStoredNewCookieToken); Assert.True(antiforgeryFeature.HaveStoredNewCookieToken);
} }
[Fact] [Fact]
public void GetAndStoreTokens_DoesNotStoreTwice() public void GetAndStoreTokens_DoesNotStoreTwice()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor var antiforgeryFeature = new AntiforgeryFeature
{ {
Value = new AntiforgeryContext HaveDeserializedCookieToken = true,
{ HaveGeneratedNewCookieToken = true,
HaveDeserializedCookieToken = true, HaveStoredNewCookieToken = true,
HaveGeneratedNewCookieToken = true, NewCookieToken = new AntiforgeryToken(),
HaveStoredNewCookieToken = true, NewCookieTokenString = "serialized-cookie-token-from-context",
NewCookieToken = new AntiforgeryToken(), NewRequestToken = new AntiforgeryToken(),
NewCookieTokenString = "serialized-cookie-token-from-context", NewRequestTokenString = "serialized-form-token-from-context",
NewRequestToken = new AntiforgeryToken(),
NewRequestTokenString = "serialized-form-token-from-context",
},
}; };
var context = CreateMockContext( var context = CreateMockContext(
new AntiforgeryOptions(), new AntiforgeryOptions(),
useOldCookie: true, useOldCookie: true,
isOldCookieValid: true, isOldCookieValid: true,
contextAccessor: contextAccessor); antiforgeryFeature: antiforgeryFeature);
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
// Act // Act
@ -470,8 +462,8 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
public async Task IsRequestValidAsync_FromStore_Failure() public async Task IsRequestValidAsync_FromStore_Failure()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor(); var antiforgeryFeature = new AntiforgeryFeature();
var context = CreateMockContext(new AntiforgeryOptions(), contextAccessor: contextAccessor); var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature);
string message; string message;
context.TokenGenerator context.TokenGenerator
@ -493,19 +485,19 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
context.TokenGenerator.Verify(); context.TokenGenerator.Verify();
// Failed _after_ updating the AntiforgeryContext. // Failed _after_ updating the AntiforgeryContext.
Assert.NotNull(contextAccessor.Value); Assert.NotNull(antiforgeryFeature);
Assert.True(contextAccessor.Value.HaveDeserializedCookieToken); Assert.True(antiforgeryFeature.HaveDeserializedCookieToken);
Assert.Equal(context.TestTokenSet.OldCookieToken, contextAccessor.Value.CookieToken); Assert.Equal(context.TestTokenSet.OldCookieToken, antiforgeryFeature.CookieToken);
Assert.True(contextAccessor.Value.HaveDeserializedRequestToken); Assert.True(antiforgeryFeature.HaveDeserializedRequestToken);
Assert.Equal(context.TestTokenSet.RequestToken, contextAccessor.Value.RequestToken); Assert.Equal(context.TestTokenSet.RequestToken, antiforgeryFeature.RequestToken);
} }
[Fact] [Fact]
public async Task IsRequestValidAsync_FromStore_Success() public async Task IsRequestValidAsync_FromStore_Success()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor(); var antiforgeryFeature = new AntiforgeryFeature();
var context = CreateMockContext(new AntiforgeryOptions(), contextAccessor: contextAccessor); var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature);
context.HttpContext.Request.Method = "POST"; context.HttpContext.Request.Method = "POST";
string message; string message;
@ -528,28 +520,25 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
Assert.True(result); Assert.True(result);
context.TokenGenerator.Verify(); context.TokenGenerator.Verify();
Assert.NotNull(contextAccessor.Value); Assert.NotNull(antiforgeryFeature);
Assert.True(contextAccessor.Value.HaveDeserializedCookieToken); Assert.True(antiforgeryFeature.HaveDeserializedCookieToken);
Assert.Equal(context.TestTokenSet.OldCookieToken, contextAccessor.Value.CookieToken); Assert.Equal(context.TestTokenSet.OldCookieToken, antiforgeryFeature.CookieToken);
Assert.True(contextAccessor.Value.HaveDeserializedRequestToken); Assert.True(antiforgeryFeature.HaveDeserializedRequestToken);
Assert.Equal(context.TestTokenSet.RequestToken, contextAccessor.Value.RequestToken); Assert.Equal(context.TestTokenSet.RequestToken, antiforgeryFeature.RequestToken);
} }
[Fact] [Fact]
public async Task IsRequestValidAsync_DoesNotDeserializeTwice() public async Task IsRequestValidAsync_DoesNotDeserializeTwice()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor var antiforgeryFeature = new AntiforgeryFeature
{ {
Value = new AntiforgeryContext HaveDeserializedCookieToken = true,
{ CookieToken = new AntiforgeryToken(),
HaveDeserializedCookieToken = true, HaveDeserializedRequestToken = true,
CookieToken = new AntiforgeryToken(), RequestToken = new AntiforgeryToken(),
HaveDeserializedRequestToken = true,
RequestToken = new AntiforgeryToken(),
},
}; };
var context = CreateMockContext(new AntiforgeryOptions(), contextAccessor: contextAccessor); var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature);
context.HttpContext.Request.Method = "POST"; context.HttpContext.Request.Method = "POST";
string message; string message;
@ -557,8 +546,8 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
.Setup(o => o.TryValidateTokenSet( .Setup(o => o.TryValidateTokenSet(
context.HttpContext, context.HttpContext,
It.IsAny<ClaimsPrincipal>(), It.IsAny<ClaimsPrincipal>(),
contextAccessor.Value.CookieToken, antiforgeryFeature.CookieToken,
contextAccessor.Value.RequestToken, antiforgeryFeature.RequestToken,
out message)) out message))
.Returns(true) .Returns(true)
.Verifiable(); .Verifiable();
@ -712,8 +701,8 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
public async Task ValidateRequestAsync_FromStore_Failure() public async Task ValidateRequestAsync_FromStore_Failure()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor(); var antiforgeryFeature = new AntiforgeryFeature();
var context = CreateMockContext(new AntiforgeryOptions(), contextAccessor: contextAccessor); var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature);
var message = "my-message"; var message = "my-message";
context.TokenGenerator context.TokenGenerator
@ -734,19 +723,19 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
context.TokenGenerator.Verify(); context.TokenGenerator.Verify();
// Failed _after_ updating the AntiforgeryContext. // Failed _after_ updating the AntiforgeryContext.
Assert.NotNull(contextAccessor.Value); Assert.NotNull(antiforgeryFeature);
Assert.True(contextAccessor.Value.HaveDeserializedCookieToken); Assert.True(antiforgeryFeature.HaveDeserializedCookieToken);
Assert.Equal(context.TestTokenSet.OldCookieToken, contextAccessor.Value.CookieToken); Assert.Equal(context.TestTokenSet.OldCookieToken, antiforgeryFeature.CookieToken);
Assert.True(contextAccessor.Value.HaveDeserializedRequestToken); Assert.True(antiforgeryFeature.HaveDeserializedRequestToken);
Assert.Equal(context.TestTokenSet.RequestToken, contextAccessor.Value.RequestToken); Assert.Equal(context.TestTokenSet.RequestToken, antiforgeryFeature.RequestToken);
} }
[Fact] [Fact]
public async Task ValidateRequestAsync_FromStore_Success() public async Task ValidateRequestAsync_FromStore_Success()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor(); var antiforgeryFeature = new AntiforgeryFeature();
var context = CreateMockContext(new AntiforgeryOptions(), contextAccessor: contextAccessor); var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature);
string message; string message;
context.TokenGenerator context.TokenGenerator
@ -767,11 +756,11 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
// Assert // Assert
context.TokenGenerator.Verify(); context.TokenGenerator.Verify();
Assert.NotNull(contextAccessor.Value); Assert.NotNull(antiforgeryFeature);
Assert.True(contextAccessor.Value.HaveDeserializedCookieToken); Assert.True(antiforgeryFeature.HaveDeserializedCookieToken);
Assert.Equal(context.TestTokenSet.OldCookieToken, contextAccessor.Value.CookieToken); Assert.Equal(context.TestTokenSet.OldCookieToken, antiforgeryFeature.CookieToken);
Assert.True(contextAccessor.Value.HaveDeserializedRequestToken); Assert.True(antiforgeryFeature.HaveDeserializedRequestToken);
Assert.Equal(context.TestTokenSet.RequestToken, contextAccessor.Value.RequestToken); Assert.Equal(context.TestTokenSet.RequestToken, antiforgeryFeature.RequestToken);
} }
[Fact] [Fact]
@ -881,25 +870,22 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
public async Task ValidateRequestAsync_DoesNotDeserializeTwice() public async Task ValidateRequestAsync_DoesNotDeserializeTwice()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor var antiforgeryFeature = new AntiforgeryFeature
{ {
Value = new AntiforgeryContext HaveDeserializedCookieToken = true,
{ CookieToken = new AntiforgeryToken(),
HaveDeserializedCookieToken = true, HaveDeserializedRequestToken = true,
CookieToken = new AntiforgeryToken(), RequestToken = new AntiforgeryToken(),
HaveDeserializedRequestToken = true,
RequestToken = new AntiforgeryToken(),
},
}; };
var context = CreateMockContext(new AntiforgeryOptions(), contextAccessor: contextAccessor); var context = CreateMockContext(new AntiforgeryOptions(), antiforgeryFeature: antiforgeryFeature);
string message; string message;
context.TokenGenerator context.TokenGenerator
.Setup(o => o.TryValidateTokenSet( .Setup(o => o.TryValidateTokenSet(
context.HttpContext, context.HttpContext,
It.IsAny<ClaimsPrincipal>(), It.IsAny<ClaimsPrincipal>(),
contextAccessor.Value.CookieToken, antiforgeryFeature.CookieToken,
contextAccessor.Value.RequestToken, antiforgeryFeature.RequestToken,
out message)) out message))
.Returns(true) .Returns(true)
.Verifiable(); .Verifiable();
@ -1056,14 +1042,14 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
{ {
SuppressXFrameOptionsHeader = suppressXFrameOptions SuppressXFrameOptionsHeader = suppressXFrameOptions
}; };
var contextAccessor = new DefaultAntiforgeryContextAccessor(); var antiforgeryFeature = new AntiforgeryFeature();
// Generate a new cookie. // Generate a new cookie.
var context = CreateMockContext( var context = CreateMockContext(
options, options,
useOldCookie: false, useOldCookie: false,
isOldCookieValid: false, isOldCookieValid: false,
contextAccessor: contextAccessor); antiforgeryFeature: antiforgeryFeature);
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
// Act // Act
@ -1073,36 +1059,33 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
var xFrameOptions = context.HttpContext.Response.Headers["X-Frame-Options"]; var xFrameOptions = context.HttpContext.Response.Headers["X-Frame-Options"];
Assert.Equal(expectedHeaderValue, xFrameOptions); Assert.Equal(expectedHeaderValue, xFrameOptions);
Assert.NotNull(contextAccessor.Value); Assert.NotNull(antiforgeryFeature);
Assert.True(contextAccessor.Value.HaveDeserializedCookieToken); Assert.True(antiforgeryFeature.HaveDeserializedCookieToken);
Assert.Equal(context.TestTokenSet.OldCookieToken, contextAccessor.Value.CookieToken); Assert.Equal(context.TestTokenSet.OldCookieToken, antiforgeryFeature.CookieToken);
Assert.True(contextAccessor.Value.HaveGeneratedNewCookieToken); Assert.True(antiforgeryFeature.HaveGeneratedNewCookieToken);
Assert.Equal(context.TestTokenSet.NewCookieToken, contextAccessor.Value.NewCookieToken); Assert.Equal(context.TestTokenSet.NewCookieToken, antiforgeryFeature.NewCookieToken);
Assert.Equal(context.TestTokenSet.NewCookieTokenString, contextAccessor.Value.NewCookieTokenString); Assert.Equal(context.TestTokenSet.NewCookieTokenString, antiforgeryFeature.NewCookieTokenString);
Assert.True(contextAccessor.Value.HaveStoredNewCookieToken); Assert.True(antiforgeryFeature.HaveStoredNewCookieToken);
} }
[Fact] [Fact]
public void SetCookieTokenAndHeader_DoesNotDeserializeTwice() public void SetCookieTokenAndHeader_DoesNotDeserializeTwice()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor var antiforgeryFeature = new AntiforgeryFeature
{ {
Value = new AntiforgeryContext HaveDeserializedCookieToken = true,
{ HaveGeneratedNewCookieToken = true,
HaveDeserializedCookieToken = true, NewCookieToken = new AntiforgeryToken(),
HaveGeneratedNewCookieToken = true, NewCookieTokenString = "serialized-cookie-token-from-context",
NewCookieToken = new AntiforgeryToken(), NewRequestToken = new AntiforgeryToken(),
NewCookieTokenString = "serialized-cookie-token-from-context", NewRequestTokenString = "serialized-form-token-from-context",
NewRequestToken = new AntiforgeryToken(),
NewRequestTokenString = "serialized-form-token-from-context",
},
}; };
var context = CreateMockContext( var context = CreateMockContext(
new AntiforgeryOptions(), new AntiforgeryOptions(),
useOldCookie: true, useOldCookie: true,
isOldCookieValid: true, isOldCookieValid: true,
contextAccessor: contextAccessor); antiforgeryFeature: antiforgeryFeature);
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
context.TokenStore context.TokenStore
@ -1132,24 +1115,21 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
public void SetCookieTokenAndHeader_DoesNotStoreTwice() public void SetCookieTokenAndHeader_DoesNotStoreTwice()
{ {
// Arrange // Arrange
var contextAccessor = new DefaultAntiforgeryContextAccessor var antiforgeryFeature = new AntiforgeryFeature
{ {
Value = new AntiforgeryContext HaveDeserializedCookieToken = true,
{ HaveGeneratedNewCookieToken = true,
HaveDeserializedCookieToken = true, HaveStoredNewCookieToken = true,
HaveGeneratedNewCookieToken = true, NewCookieToken = new AntiforgeryToken(),
HaveStoredNewCookieToken = true, NewCookieTokenString = "serialized-cookie-token-from-context",
NewCookieToken = new AntiforgeryToken(), NewRequestToken = new AntiforgeryToken(),
NewCookieTokenString = "serialized-cookie-token-from-context", NewRequestTokenString = "serialized-form-token-from-context",
NewRequestToken = new AntiforgeryToken(),
NewRequestTokenString = "serialized-form-token-from-context",
},
}; };
var context = CreateMockContext( var context = CreateMockContext(
new AntiforgeryOptions(), new AntiforgeryOptions(),
useOldCookie: true, useOldCookie: true,
isOldCookieValid: true, isOldCookieValid: true,
contextAccessor: contextAccessor); antiforgeryFeature: antiforgeryFeature);
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
// Act // Act
@ -1192,21 +1172,20 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
loggerFactory: loggerFactory); loggerFactory: loggerFactory);
} }
private IServiceProvider GetServices(IAntiforgeryContextAccessor contextAccessor) private IServiceProvider GetServices()
{ {
var builder = new ServiceCollection(); var builder = new ServiceCollection();
builder.AddSingleton<IAntiforgeryContextAccessor>(contextAccessor);
builder.AddSingleton<ILoggerFactory>(new LoggerFactory()); builder.AddSingleton<ILoggerFactory>(new LoggerFactory());
return builder.BuildServiceProvider(); return builder.BuildServiceProvider();
} }
private HttpContext GetHttpContext(IAntiforgeryContextAccessor contextAccessor = null) private HttpContext GetHttpContext(IAntiforgeryFeature antiforgeryFeature = null)
{ {
var httpContext = new DefaultHttpContext(); var httpContext = new DefaultHttpContext();
contextAccessor = contextAccessor ?? new DefaultAntiforgeryContextAccessor(); antiforgeryFeature = antiforgeryFeature ?? new AntiforgeryFeature();
httpContext.RequestServices = GetServices(contextAccessor); httpContext.Features.Set(antiforgeryFeature);
httpContext.RequestServices = GetServices();
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity("some-auth")); httpContext.User = new ClaimsPrincipal(new ClaimsIdentity("some-auth"));
return httpContext; return httpContext;
@ -1276,10 +1255,10 @@ namespace Microsoft.AspNetCore.Antiforgery.Internal
AntiforgeryOptions options, AntiforgeryOptions options,
bool useOldCookie = false, bool useOldCookie = false,
bool isOldCookieValid = true, bool isOldCookieValid = true,
IAntiforgeryContextAccessor contextAccessor = null) IAntiforgeryFeature antiforgeryFeature = null)
{ {
// Arrange // Arrange
var httpContext = GetHttpContext(contextAccessor); var httpContext = GetHttpContext(antiforgeryFeature);
var testTokenSet = GetTokenSet(); var testTokenSet = GetTokenSet();
var mockSerializer = GetTokenSerializer(testTokenSet); var mockSerializer = GetTokenSerializer(testTokenSet);