Adds a IsRequestValidAsync method

Some other misc cleanup
- docs for IAntiforgeryTokenGenerator
- Add HttpContext parameter where to all IAntiforgeryGenerator methods
- rename parameters on DefaultAntiforgery
This commit is contained in:
Ryan Nowak 2016-02-02 10:37:39 -08:00
parent 0ddfa5f0d8
commit 20140c4c15
9 changed files with 510 additions and 230 deletions

View File

@ -36,75 +36,100 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
/// <inheritdoc /> /// <inheritdoc />
public IHtmlContent GetHtml(HttpContext context) public IHtmlContent GetHtml(HttpContext httpContext)
{ {
if (context == null) if (httpContext == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(httpContext));
} }
CheckSSLConfig(context); CheckSSLConfig(httpContext);
var tokenSet = GetAndStoreTokens(context); var tokenSet = GetAndStoreTokens(httpContext);
return new InputContent(_options.FormFieldName, tokenSet.RequestToken); return new InputContent(_options.FormFieldName, tokenSet.RequestToken);
} }
/// <inheritdoc /> /// <inheritdoc />
public AntiforgeryTokenSet GetAndStoreTokens(HttpContext context) public AntiforgeryTokenSet GetAndStoreTokens(HttpContext httpContext)
{ {
if (context == null) if (httpContext == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(httpContext));
} }
CheckSSLConfig(context); CheckSSLConfig(httpContext);
var tokenSet = GetTokensInternal(context); var tokenSet = GetTokensInternal(httpContext);
if (tokenSet.IsNewCookieToken) if (tokenSet.IsNewCookieToken)
{ {
SaveCookieTokenAndHeader(context, tokenSet.CookieToken); SaveCookieTokenAndHeader(httpContext, tokenSet.CookieToken);
} }
return Serialize(tokenSet); return Serialize(tokenSet);
} }
/// <inheritdoc /> /// <inheritdoc />
public AntiforgeryTokenSet GetTokens(HttpContext context) public AntiforgeryTokenSet GetTokens(HttpContext httpContext)
{ {
if (context == null) if (httpContext == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(httpContext));
} }
CheckSSLConfig(context); CheckSSLConfig(httpContext);
var tokenSet = GetTokensInternal(context); var tokenSet = GetTokensInternal(httpContext);
return Serialize(tokenSet); return Serialize(tokenSet);
} }
/// <inheritdoc /> /// <inheritdoc />
public async Task ValidateRequestAsync(HttpContext context) public async Task<bool> IsRequestValidAsync(HttpContext httpContext)
{ {
if (context == null) if (httpContext == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(httpContext));
} }
CheckSSLConfig(context); CheckSSLConfig(httpContext);
var tokens = await _tokenStore.GetRequestTokensAsync(context); var tokens = await _tokenStore.GetRequestTokensAsync(httpContext);
ValidateTokens(context, tokens);
// Extract cookie & request tokens
var deserializedCookieToken = _tokenSerializer.Deserialize(tokens.CookieToken);
var deserializedRequestToken = _tokenSerializer.Deserialize(tokens.RequestToken);
// Validate
string message;
return _tokenGenerator.TryValidateTokenSet(
httpContext,
deserializedCookieToken,
deserializedRequestToken,
out message);
} }
/// <inheritdoc /> /// <inheritdoc />
public void ValidateTokens(HttpContext context, AntiforgeryTokenSet antiforgeryTokenSet) public async Task ValidateRequestAsync(HttpContext httpContext)
{ {
if (context == null) if (httpContext == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(httpContext));
} }
CheckSSLConfig(context); CheckSSLConfig(httpContext);
var tokens = await _tokenStore.GetRequestTokensAsync(httpContext);
ValidateTokens(httpContext, tokens);
}
/// <inheritdoc />
public void ValidateTokens(HttpContext httpContext, AntiforgeryTokenSet antiforgeryTokenSet)
{
if (httpContext == null)
{
throw new ArgumentNullException(nameof(httpContext));
}
CheckSSLConfig(httpContext);
if (string.IsNullOrEmpty(antiforgeryTokenSet.CookieToken)) if (string.IsNullOrEmpty(antiforgeryTokenSet.CookieToken))
{ {
@ -125,25 +150,30 @@ namespace Microsoft.AspNetCore.Antiforgery
var deserializedRequestToken = _tokenSerializer.Deserialize(antiforgeryTokenSet.RequestToken); var deserializedRequestToken = _tokenSerializer.Deserialize(antiforgeryTokenSet.RequestToken);
// Validate // Validate
_tokenGenerator.ValidateTokens( string message;
context, if (!_tokenGenerator.TryValidateTokenSet(
httpContext,
deserializedCookieToken, deserializedCookieToken,
deserializedRequestToken); deserializedRequestToken,
out message))
{
throw new AntiforgeryValidationException(message);
}
} }
/// <inheritdoc /> /// <inheritdoc />
public void SetCookieTokenAndHeader(HttpContext context) public void SetCookieTokenAndHeader(HttpContext httpContext)
{ {
if (context == null) if (httpContext == null)
{ {
throw new ArgumentNullException(nameof(context)); throw new ArgumentNullException(nameof(httpContext));
} }
CheckSSLConfig(context); CheckSSLConfig(httpContext);
var cookieToken = GetCookieTokenDoesNotThrow(context); var cookieToken = GetCookieTokenDoesNotThrow(httpContext);
cookieToken = ValidateAndGenerateNewCookieToken(cookieToken); cookieToken = ValidateAndGenerateNewCookieToken(cookieToken);
SaveCookieTokenAndHeader(context, cookieToken); SaveCookieTokenAndHeader(httpContext, cookieToken);
} }
// This method returns null if oldCookieToken is valid. // This method returns null if oldCookieToken is valid.
@ -208,16 +238,16 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
} }
private AntiforgeryTokenSetInternal GetTokensInternal(HttpContext context) private AntiforgeryTokenSetInternal GetTokensInternal(HttpContext httpContext)
{ {
var cookieToken = GetCookieTokenDoesNotThrow(context); var cookieToken = GetCookieTokenDoesNotThrow(httpContext);
var newCookieToken = ValidateAndGenerateNewCookieToken(cookieToken); var newCookieToken = ValidateAndGenerateNewCookieToken(cookieToken);
if (newCookieToken != null) if (newCookieToken != null)
{ {
cookieToken = newCookieToken; cookieToken = newCookieToken;
} }
var requestToken = _tokenGenerator.GenerateRequestToken( var requestToken = _tokenGenerator.GenerateRequestToken(
context, httpContext,
cookieToken); cookieToken);
return new AntiforgeryTokenSetInternal() return new AntiforgeryTokenSetInternal()

View File

@ -2,7 +2,6 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Diagnostics;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Principal; using System.Security.Principal;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@ -22,6 +21,7 @@ namespace Microsoft.AspNetCore.Antiforgery
_additionalDataProvider = additionalDataProvider; _additionalDataProvider = additionalDataProvider;
} }
/// <inheritdoc />
public AntiforgeryToken GenerateCookieToken() public AntiforgeryToken GenerateCookieToken()
{ {
return new AntiforgeryToken() return new AntiforgeryToken()
@ -31,6 +31,7 @@ namespace Microsoft.AspNetCore.Antiforgery
}; };
} }
/// <inheritdoc />
public AntiforgeryToken GenerateRequestToken( public AntiforgeryToken GenerateRequestToken(
HttpContext httpContext, HttpContext httpContext,
AntiforgeryToken cookieToken) AntiforgeryToken cookieToken)
@ -40,7 +41,17 @@ namespace Microsoft.AspNetCore.Antiforgery
throw new ArgumentNullException(nameof(httpContext)); throw new ArgumentNullException(nameof(httpContext));
} }
Debug.Assert(IsCookieTokenValid(cookieToken)); if (cookieToken == null)
{
throw new ArgumentNullException(nameof(cookieToken));
}
if (!IsCookieTokenValid(cookieToken))
{
throw new ArgumentException(
Resources.Antiforgery_CookieToken_IsInvalid,
nameof(cookieToken));
}
var requestToken = new AntiforgeryToken() var requestToken = new AntiforgeryToken()
{ {
@ -87,15 +98,18 @@ namespace Microsoft.AspNetCore.Antiforgery
return requestToken; return requestToken;
} }
/// <inheritdoc />
public bool IsCookieTokenValid(AntiforgeryToken cookieToken) public bool IsCookieTokenValid(AntiforgeryToken cookieToken)
{ {
return (cookieToken != null && cookieToken.IsCookieToken); return cookieToken != null && cookieToken.IsCookieToken;
} }
public void ValidateTokens( /// <inheritdoc />
public bool TryValidateTokenSet(
HttpContext httpContext, HttpContext httpContext,
AntiforgeryToken cookieToken, AntiforgeryToken cookieToken,
AntiforgeryToken requestToken) AntiforgeryToken requestToken,
out string message)
{ {
if (httpContext == null) if (httpContext == null)
{ {
@ -119,13 +133,15 @@ namespace Microsoft.AspNetCore.Antiforgery
// Do the tokens have the correct format? // Do the tokens have the correct format?
if (!cookieToken.IsCookieToken || requestToken.IsCookieToken) if (!cookieToken.IsCookieToken || requestToken.IsCookieToken)
{ {
throw new AntiforgeryValidationException(Resources.AntiforgeryToken_TokensSwapped); message = Resources.AntiforgeryToken_TokensSwapped;
return false;
} }
// Are the security tokens embedded in each incoming token identical? // Are the security tokens embedded in each incoming token identical?
if (!object.Equals(cookieToken.SecurityToken, requestToken.SecurityToken)) if (!object.Equals(cookieToken.SecurityToken, requestToken.SecurityToken))
{ {
throw new AntiforgeryValidationException(Resources.AntiforgeryToken_SecurityTokenMismatch); message = Resources.AntiforgeryToken_SecurityTokenMismatch;
return false;
} }
// Is the incoming token meant for the current user? // Is the incoming token meant for the current user?
@ -153,21 +169,26 @@ namespace Microsoft.AspNetCore.Antiforgery
if (!comparer.Equals(requestToken.Username, currentUsername)) if (!comparer.Equals(requestToken.Username, currentUsername))
{ {
throw new AntiforgeryValidationException( message = Resources.FormatAntiforgeryToken_UsernameMismatch(requestToken.Username, currentUsername);
Resources.FormatAntiforgeryToken_UsernameMismatch(requestToken.Username, currentUsername)); return false;
} }
if (!object.Equals(requestToken.ClaimUid, currentClaimUid)) if (!object.Equals(requestToken.ClaimUid, currentClaimUid))
{ {
throw new AntiforgeryValidationException(Resources.AntiforgeryToken_ClaimUidMismatch); message = Resources.AntiforgeryToken_ClaimUidMismatch;
return false;
} }
// Is the AdditionalData valid? // Is the AdditionalData valid?
if (_additionalDataProvider != null && if (_additionalDataProvider != null &&
!_additionalDataProvider.ValidateAdditionalData(httpContext, requestToken.AdditionalData)) !_additionalDataProvider.ValidateAdditionalData(httpContext, requestToken.AdditionalData))
{ {
throw new AntiforgeryValidationException(Resources.AntiforgeryToken_AdditionalDataCheckFailed); message = Resources.AntiforgeryToken_AdditionalDataCheckFailed;
return false;
} }
message = null;
return true;
} }
private static BinaryBlob GetClaimUidBlob(string base64ClaimUid) private static BinaryBlob GetClaimUidBlob(string base64ClaimUid)

View File

@ -16,7 +16,7 @@ namespace Microsoft.AspNetCore.Antiforgery
/// <summary> /// <summary>
/// Generates an &lt;input type="hidden"&gt; element for an antiforgery token. /// Generates an &lt;input type="hidden"&gt; element for an antiforgery token.
/// </summary> /// </summary>
/// <param name="context">The <see cref="HttpContext"/> associated with the current request.</param> /// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
/// <returns> /// <returns>
/// A <see cref="IHtmlContent"/> containing an &lt;input type="hidden"&gt; element. This element should be put /// A <see cref="IHtmlContent"/> containing an &lt;input type="hidden"&gt; element. This element should be put
/// inside a &lt;form&gt;. /// inside a &lt;form&gt;.
@ -25,50 +25,63 @@ namespace Microsoft.AspNetCore.Antiforgery
/// This method has a side effect: /// This method has a side effect:
/// A response cookie is set if there is no valid cookie associated with the request. /// A response cookie is set if there is no valid cookie associated with the request.
/// </remarks> /// </remarks>
IHtmlContent GetHtml(HttpContext context); IHtmlContent GetHtml(HttpContext httpContext);
/// <summary> /// <summary>
/// Generates an <see cref="AntiforgeryTokenSet"/> for this request and stores the cookie token /// Generates an <see cref="AntiforgeryTokenSet"/> for this request and stores the cookie token
/// in the response. /// in the response.
/// </summary> /// </summary>
/// <param name="context">The <see cref="HttpContext"/> associated with the current request.</param> /// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
/// <returns>An <see cref="AntiforgeryTokenSet" /> with tokens for the response.</returns> /// <returns>An <see cref="AntiforgeryTokenSet" /> with tokens for the response.</returns>
/// <remarks> /// <remarks>
/// This method has a side effect: /// This method has a side effect:
/// A response cookie is set if there is no valid cookie associated with the request. /// A response cookie is set if there is no valid cookie associated with the request.
/// </remarks> /// </remarks>
AntiforgeryTokenSet GetAndStoreTokens(HttpContext context); AntiforgeryTokenSet GetAndStoreTokens(HttpContext httpContext);
/// <summary> /// <summary>
/// Generates an <see cref="AntiforgeryTokenSet"/> for this request. /// Generates an <see cref="AntiforgeryTokenSet"/> for this request.
/// </summary> /// </summary>
/// <param name="context">The <see cref="HttpContext"/> associated with the current request.</param> /// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
/// <remarks> /// <remarks>
/// Unlike <see cref="GetAndStoreTokens(HttpContext)"/>, this method has no side effect. The caller /// Unlike <see cref="GetAndStoreTokens(HttpContext)"/>, this method has no side effect. The caller
/// is responsible for setting the response cookie and injecting the returned /// is responsible for setting the response cookie and injecting the returned
/// form token as appropriate. /// form token as appropriate.
/// </remarks> /// </remarks>
AntiforgeryTokenSet GetTokens(HttpContext context); AntiforgeryTokenSet GetTokens(HttpContext httpContext);
/// <summary>
/// Asynchronously returns a value indicating whether the request contains a valid antiforgery token.
/// </summary>
/// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
/// <returns>
/// A <see cref="Task{bool}"/> that, when completed, returns <c>true</c> if the request contains a
/// valid antiforgery token, otherwise returns <c>false</c>.
/// </returns>
Task<bool> IsRequestValidAsync(HttpContext httpContext);
/// <summary> /// <summary>
/// Validates an antiforgery token that was supplied as part of the request. /// Validates an antiforgery token that was supplied as part of the request.
/// </summary> /// </summary>
/// <param name="context">The <see cref="HttpContext"/> associated with the current request.</param> /// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
Task ValidateRequestAsync(HttpContext context); /// <exception cref="AntiforgeryValidationException">
/// Thrown when the request does not include a valid antiforgery token.
/// </exception>
Task ValidateRequestAsync(HttpContext httpContext);
/// <summary> /// <summary>
/// Validates an <see cref="AntiforgeryTokenSet"/> for the current request. /// Validates an <see cref="AntiforgeryTokenSet"/> for the current request.
/// </summary> /// </summary>
/// <param name="context">The <see cref="HttpContext"/> associated with the current request.</param> /// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
/// <param name="antiforgeryTokenSet"> /// <param name="antiforgeryTokenSet">
/// The <see cref="AntiforgeryTokenSet"/> (cookie and request token) for this request. /// The <see cref="AntiforgeryTokenSet"/> (cookie and request token) for this request.
/// </param> /// </param>
void ValidateTokens(HttpContext context, AntiforgeryTokenSet antiforgeryTokenSet); void ValidateTokens(HttpContext httpContext, AntiforgeryTokenSet antiforgeryTokenSet);
/// <summary> /// <summary>
/// Generates and stores an antiforgery cookie token if one is not available or not valid. /// Generates and stores an antiforgery cookie token if one is not available or not valid.
/// </summary> /// </summary>
/// <param name="context">The <see cref="HttpContext"/> associated with the current request.</param> /// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
void SetCookieTokenAndHeader(HttpContext context); void SetCookieTokenAndHeader(HttpContext httpContext);
} }
} }

View File

@ -10,23 +10,41 @@ namespace Microsoft.AspNetCore.Antiforgery
/// </summary> /// </summary>
public interface IAntiforgeryTokenGenerator public interface IAntiforgeryTokenGenerator
{ {
// Generates a new random cookie token. /// <summary>
/// Generates a new random cookie token.
/// </summary>
/// <returns>An <see cref="AntiforgeryToken"/>.</returns>
AntiforgeryToken GenerateCookieToken(); AntiforgeryToken GenerateCookieToken();
// Given a cookie token, generates a corresponding request token. /// <summary>
// The incoming cookie token must be valid. /// Generates a request token corresponding to <paramref name="cookieToken"/>.
AntiforgeryToken GenerateRequestToken( /// </summary>
HttpContext httpContext, /// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
AntiforgeryToken cookieToken); /// <param name="cookieToken">A valid cookie token.</param>
/// <returns>An <see cref="AntiforgeryToken"/>.</returns>
AntiforgeryToken GenerateRequestToken(HttpContext httpContext, AntiforgeryToken cookieToken);
// Determines whether an existing cookie token is valid (well-formed). /// <summary>
// If it is not, the caller must call GenerateCookieToken() before calling GenerateFormToken(). /// Attempts to validate a cookie token.
/// </summary>
/// <param name="cookieToken">A valid cookie token.</param>
/// <returns><c>true</c> if the cookie token is valid, otherwise <c>false</c>.</returns>
bool IsCookieTokenValid(AntiforgeryToken cookieToken); bool IsCookieTokenValid(AntiforgeryToken cookieToken);
// Validates a (cookie, request) token pair. /// <summary>
void ValidateTokens( /// Attempts to validate a cookie and request token set for the given <paramref name="httpContext"/>.
/// </summary>
/// <param name="httpContext">The <see cref="HttpContext"/> associated with the current request.</param>
/// <param name="cookieToken">A cookie token.</param>
/// <param name="requestToken">A request token.</param>
/// <param name="message">
/// Will be set to the validation message if the tokens are invalid, otherwise <c>null</c>.
/// </param>
/// <returns><c>true</c> if the tokens are valid, otherwise <c>false</c>.</returns>
bool TryValidateTokenSet(
HttpContext httpContext, HttpContext httpContext,
AntiforgeryToken cookieToken, AntiforgeryToken cookieToken,
AntiforgeryToken requestToken); AntiforgeryToken requestToken,
out string message);
} }
} }

View File

@ -138,6 +138,14 @@ namespace Microsoft.AspNetCore.Antiforgery
return string.Format(CultureInfo.CurrentCulture, GetString("AntiforgeryWorker_RequireSSL"), p0, p1, p2); return string.Format(CultureInfo.CurrentCulture, GetString("AntiforgeryWorker_RequireSSL"), p0, p1, p2);
} }
/// <summary>
/// The required antiforgery cookie "{0}" is not present.
/// </summary>
internal static string Antiforgery_CookieToken_IsInvalid
{
get { return GetString("Antiforgery_CookieToken_IsInvalid"); }
}
/// <summary> /// <summary>
/// The required antiforgery cookie "{0}" is not present. /// The required antiforgery cookie "{0}" is not present.
/// </summary> /// </summary>

View File

@ -143,6 +143,9 @@
<value>The antiforgery system has the configuration value {0}.{1} = {2}, but the current request is not an SSL request.</value> <value>The antiforgery system has the configuration value {0}.{1} = {2}, but the current request is not an SSL request.</value>
<comment>0 = nameof(AntiforgeryOptions), 1 = nameof(RequireSsl), 2 = bool.TrueString</comment> <comment>0 = nameof(AntiforgeryOptions), 1 = nameof(RequireSsl), 2 = bool.TrueString</comment>
</data> </data>
<data name="Antiforgery_CookieToken_IsInvalid" xml:space="preserve">
<value>The antiforgery cookie token is invalid.</value>
</data>
<data name="Antiforgery_CookieToken_MustBeProvided" xml:space="preserve"> <data name="Antiforgery_CookieToken_MustBeProvided" xml:space="preserve">
<value>The required antiforgery cookie "{0}" is not present.</value> <value>The required antiforgery cookie "{0}" is not present.</value>
</data> </data>

View File

@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Microsoft.AspNetCore.Html; using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal; using Microsoft.AspNetCore.Http.Internal;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.Extensions.WebEncoders.Testing; using Microsoft.Extensions.WebEncoders.Testing;
using Moq; using Moq;
@ -34,9 +35,31 @@ namespace Microsoft.AspNetCore.Antiforgery
var exception = await Assert.ThrowsAsync<InvalidOperationException>( var exception = await Assert.ThrowsAsync<InvalidOperationException>(
async () => await antiforgery.ValidateRequestAsync(httpContext)); async () => await antiforgery.ValidateRequestAsync(httpContext));
Assert.Equal( Assert.Equal(
@"The antiforgery system has the configuration value AntiforgeryOptions.RequireSsl = true, " + @"The antiforgery system has the configuration value AntiforgeryOptions.RequireSsl = true, " +
"but the current request is not an SSL request.", "but the current request is not an SSL request.",
exception.Message); exception.Message);
}
[Fact]
public async Task ChecksSSL_IsRequestValidAsync_Throws()
{
// Arrange
var httpContext = new DefaultHttpContext();
var options = new AntiforgeryOptions()
{
RequireSsl = true
};
var antiforgery = GetAntiforgery(options);
// Act & Assert
var exception = await Assert.ThrowsAsync<InvalidOperationException>(
async () => await antiforgery.IsRequestValidAsync(httpContext));
Assert.Equal(
@"The antiforgery system has the configuration value AntiforgeryOptions.RequireSsl = true, " +
"but the current request is not an SSL request.",
exception.Message);
} }
[Fact] [Fact]
@ -56,9 +79,9 @@ namespace Microsoft.AspNetCore.Antiforgery
var exception = Assert.Throws<InvalidOperationException>( var exception = Assert.Throws<InvalidOperationException>(
() => antiforgery.ValidateTokens(httpContext, new AntiforgeryTokenSet("hello", "world"))); () => antiforgery.ValidateTokens(httpContext, new AntiforgeryTokenSet("hello", "world")));
Assert.Equal( Assert.Equal(
@"The antiforgery system has the configuration value AntiforgeryOptions.RequireSsl = true, " + @"The antiforgery system has the configuration value AntiforgeryOptions.RequireSsl = true, " +
"but the current request is not an SSL request.", "but the current request is not an SSL request.",
exception.Message); exception.Message);
} }
[Fact] [Fact]
@ -162,6 +185,11 @@ namespace Microsoft.AspNetCore.Antiforgery
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
var encoder = new HtmlTestEncoder(); var encoder = new HtmlTestEncoder();
// Setup so that the null cookie token returned is treated as invalid.
context.TokenGenerator
.Setup(o => o.IsCookieTokenValid(null))
.Returns(false);
// Act // Act
var inputElement = antiforgery.GetHtml(context.HttpContext); var inputElement = antiforgery.GetHtml(context.HttpContext);
@ -303,12 +331,10 @@ namespace Microsoft.AspNetCore.Antiforgery
isOldCookieValid: false); isOldCookieValid: false);
// This will cause the cookieToken to be null. // This will cause the cookieToken to be null.
context.TokenSerializer.Setup(o => o.Deserialize("serialized-old-cookie-token")) context.TokenSerializer
.Throws(new Exception("should be swallowed")); .Setup(o => o.Deserialize("serialized-old-cookie-token"))
.Throws(new Exception("should be swallowed"));
// Setup so that the null cookie token returned is treated as invalid.
context.TokenGenerator.Setup(o => o.IsCookieTokenValid(null))
.Returns(false);
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
// Act // Act
@ -381,7 +407,7 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
[Fact] [Fact]
public void ValidateTokens_FromInvalidStrings_Throws() public void ValidateTokens_InvalidTokens_Throws()
{ {
// Arrange // Arrange
var context = CreateMockContext(new AntiforgeryOptions()); var context = CreateMockContext(new AntiforgeryOptions());
@ -393,17 +419,20 @@ namespace Microsoft.AspNetCore.Antiforgery
.Setup(o => o.Deserialize("form-token")) .Setup(o => o.Deserialize("form-token"))
.Returns(context.TestTokenSet.RequestToken); .Returns(context.TestTokenSet.RequestToken);
context.TokenGenerator // You can't really do Moq with out-parameters :(
.Setup(o => o.ValidateTokens( var tokenGenerator = new TestTokenGenerator()
context.HttpContext, {
context.TestTokenSet.OldCookieToken, Message = "my-message",
context.TestTokenSet.RequestToken)) };
.Throws(new InvalidOperationException("my-message"));
context.TokenStore = null;
var antiforgery = GetAntiforgery(context);
// Act & assert var antiforgery = new DefaultAntiforgery(
var exception = Assert.Throws<InvalidOperationException>( new TestOptionsManager(),
tokenGenerator,
context.TokenSerializer.Object,
tokenStore: null);
// Act & Assert
var exception = Assert.Throws<AntiforgeryValidationException>(
() => antiforgery.ValidateTokens( () => antiforgery.ValidateTokens(
context.HttpContext, context.HttpContext,
new AntiforgeryTokenSet("form-token", "cookie-token"))); new AntiforgeryTokenSet("form-token", "cookie-token")));
@ -423,11 +452,14 @@ namespace Microsoft.AspNetCore.Antiforgery
.Setup(o => o.Deserialize("form-token")) .Setup(o => o.Deserialize("form-token"))
.Returns(context.TestTokenSet.RequestToken); .Returns(context.TestTokenSet.RequestToken);
string message;
context.TokenGenerator context.TokenGenerator
.Setup(o => o.ValidateTokens( .Setup(o => o.TryValidateTokenSet(
context.HttpContext, context.HttpContext,
context.TestTokenSet.OldCookieToken, context.TestTokenSet.OldCookieToken,
context.TestTokenSet.RequestToken)) context.TestTokenSet.RequestToken,
out message))
.Returns(true)
.Verifiable(); .Verifiable();
context.TokenStore = null; context.TokenStore = null;
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
@ -450,12 +482,60 @@ namespace Microsoft.AspNetCore.Antiforgery
// Act // Act
var exception = Assert.Throws<ArgumentException>( ExceptionAssert.ThrowsArgument(
() => antiforgery.ValidateTokens(context.HttpContext, tokenSet)); () => antiforgery.ValidateTokens(context.HttpContext, tokenSet),
"antiforgeryTokenSet",
"The required antiforgery cookie token must be provided.");
}
[Fact]
public async Task IsRequestValueAsync_FromStore_Failure()
{
// Arrange
var context = CreateMockContext(new AntiforgeryOptions());
string message;
context.TokenGenerator
.Setup(o => o.TryValidateTokenSet(
context.HttpContext,
context.TestTokenSet.OldCookieToken,
context.TestTokenSet.RequestToken,
out message))
.Returns(false);
var antiforgery = GetAntiforgery(context);
// Act
var result = await antiforgery.IsRequestValidAsync(context.HttpContext);
// Assert // Assert
var trimmed = exception.Message.Substring(0, exception.Message.IndexOf(Environment.NewLine)); Assert.False(result);
Assert.Equal("The required antiforgery cookie token must be provided.", trimmed); }
[Fact]
public async Task IsRequestValidAsync_FromStore_Success()
{
// Arrange
var context = CreateMockContext(new AntiforgeryOptions());
string message;
context.TokenGenerator
.Setup(o => o.TryValidateTokenSet(
context.HttpContext,
context.TestTokenSet.OldCookieToken,
context.TestTokenSet.RequestToken,
out message))
.Returns(true)
.Verifiable();
var antiforgery = GetAntiforgery(context);
// Act
var result = await antiforgery.IsRequestValidAsync(context.HttpContext);
// Assert
Assert.True(result);
context.TokenGenerator.Verify();
} }
[Fact] [Fact]
@ -464,17 +544,20 @@ namespace Microsoft.AspNetCore.Antiforgery
// Arrange // Arrange
var context = CreateMockContext(new AntiforgeryOptions()); var context = CreateMockContext(new AntiforgeryOptions());
context.TokenGenerator // You can't really do Moq with out-parameters :(
.Setup(o => o.ValidateTokens( var tokenGenerator = new TestTokenGenerator()
context.HttpContext, {
context.TestTokenSet.OldCookieToken, Message = "my-message",
context.TestTokenSet.RequestToken)) };
.Throws(new InvalidOperationException("my-message"));
var antiforgery = GetAntiforgery(context); var antiforgery = new DefaultAntiforgery(
new TestOptionsManager(),
tokenGenerator,
context.TokenSerializer.Object,
context.TokenStore.Object);
// Act & assert // Act & assert
var exception = await Assert.ThrowsAsync<InvalidOperationException>( var exception = await Assert.ThrowsAsync<AntiforgeryValidationException>(
async () => await antiforgery.ValidateRequestAsync(context.HttpContext)); async () => await antiforgery.ValidateRequestAsync(context.HttpContext));
Assert.Equal("my-message", exception.Message); Assert.Equal("my-message", exception.Message);
} }
@ -485,11 +568,14 @@ namespace Microsoft.AspNetCore.Antiforgery
// Arrange // Arrange
var context = CreateMockContext(new AntiforgeryOptions()); var context = CreateMockContext(new AntiforgeryOptions());
string message;
context.TokenGenerator context.TokenGenerator
.Setup(o => o.ValidateTokens( .Setup(o => o.TryValidateTokenSet(
context.HttpContext, context.HttpContext,
context.TestTokenSet.OldCookieToken, context.TestTokenSet.OldCookieToken,
context.TestTokenSet.RequestToken)) context.TestTokenSet.RequestToken,
out message))
.Returns(true)
.Verifiable(); .Verifiable();
var antiforgery = GetAntiforgery(context); var antiforgery = GetAntiforgery(context);
@ -696,5 +782,35 @@ namespace Microsoft.AspNetCore.Antiforgery
{ {
public AntiforgeryOptions Value { get; set; } = new AntiforgeryOptions(); public AntiforgeryOptions Value { get; set; } = new AntiforgeryOptions();
} }
private class TestTokenGenerator : IAntiforgeryTokenGenerator
{
public string Message { get; set; }
public AntiforgeryToken GenerateCookieToken()
{
throw new NotImplementedException();
}
public AntiforgeryToken GenerateRequestToken(HttpContext httpContext, AntiforgeryToken cookieToken)
{
throw new NotImplementedException();
}
public bool IsCookieTokenValid(AntiforgeryToken cookieToken)
{
throw new NotImplementedException();
}
public bool TryValidateTokenSet(
HttpContext httpContext,
AntiforgeryToken cookieToken,
AntiforgeryToken requestToken,
out string message)
{
message = Message;
return false;
}
}
} }
} }

View File

@ -5,6 +5,7 @@ using System;
using System.Security.Claims; using System.Security.Claims;
using System.Security.Cryptography; using System.Security.Cryptography;
using Microsoft.AspNetCore.Http.Internal; using Microsoft.AspNetCore.Http.Internal;
using Microsoft.AspNetCore.Testing;
using Moq; using Moq;
using Xunit; using Xunit;
@ -28,7 +29,27 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
[Fact] [Fact]
public void GenerateFormToken_AnonymousUser() public void GenerateRequestToken_InvalidCookieToken()
{
// Arrange
var cookieToken = new AntiforgeryToken() { IsCookieToken = false };
var httpContext = new DefaultHttpContext();
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity());
Assert.False(httpContext.User.Identity.IsAuthenticated);
var tokenProvider = new DefaultAntiforgeryTokenGenerator(
claimUidExtractor: null,
additionalDataProvider: null);
// Act & Assert
ExceptionAssert.ThrowsArgument(
() => tokenProvider.GenerateRequestToken(httpContext, cookieToken),
"cookieToken",
"The antiforgery cookie token is invalid.");
}
[Fact]
public void GenerateRequestToken_AnonymousUser()
{ {
// Arrange // Arrange
var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var cookieToken = new AntiforgeryToken() { IsCookieToken = true };
@ -53,7 +74,7 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
[Fact] [Fact]
public void GenerateFormToken_AuthenticatedWithoutUsernameAndNoAdditionalData_NoAdditionalData() public void GenerateRequestToken_AuthenticatedWithoutUsernameAndNoAdditionalData_NoAdditionalData()
{ {
// Arrange // Arrange
var cookieToken = new AntiforgeryToken() var cookieToken = new AntiforgeryToken()
@ -87,7 +108,7 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
[Fact] [Fact]
public void GenerateFormToken_AuthenticatedWithoutUsername_WithAdditionalData() public void GenerateRequestToken_AuthenticatedWithoutUsername_WithAdditionalData()
{ {
// Arrange // Arrange
var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var cookieToken = new AntiforgeryToken() { IsCookieToken = true };
@ -118,7 +139,7 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
[Fact] [Fact]
public void GenerateFormToken_ClaimsBasedIdentity() public void GenerateRequestToken_ClaimsBasedIdentity()
{ {
// Arrange // Arrange
var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var cookieToken = new AntiforgeryToken() { IsCookieToken = true };
@ -156,7 +177,7 @@ namespace Microsoft.AspNetCore.Antiforgery
} }
[Fact] [Fact]
public void GenerateFormToken_RegularUserWithUsername() public void GenerateRequestToken_RegularUserWithUsername()
{ {
// Arrange // Arrange
var cookieToken = new AntiforgeryToken() { IsCookieToken = true }; var cookieToken = new AntiforgeryToken() { IsCookieToken = true };
@ -202,10 +223,10 @@ namespace Microsoft.AspNetCore.Antiforgery
additionalDataProvider: null); additionalDataProvider: null);
// Act // Act
bool retVal = tokenProvider.IsCookieTokenValid(cookieToken); var isValid = tokenProvider.IsCookieTokenValid(cookieToken);
// Assert // Assert
Assert.False(retVal); Assert.False(isValid);
} }
[Fact] [Fact]
@ -246,7 +267,7 @@ namespace Microsoft.AspNetCore.Antiforgery
[Fact] [Fact]
public void ValidateTokens_CookieTokenMissing() public void TryValidateTokenSet_CookieTokenMissing()
{ {
// Arrange // Arrange
var httpContext = new DefaultHttpContext(); var httpContext = new DefaultHttpContext();
@ -254,98 +275,126 @@ namespace Microsoft.AspNetCore.Antiforgery
var fieldtoken = new AntiforgeryToken() { IsCookieToken = false }; var fieldtoken = new AntiforgeryToken() { IsCookieToken = false };
var tokenProvider = new DefaultAntiforgeryTokenGenerator(
claimUidExtractor: null,
additionalDataProvider: null);
// Act & assert
var ex = Assert.Throws<ArgumentNullException>(
() => tokenProvider.ValidateTokens(httpContext, null, fieldtoken));
var trimmed = ex.Message.Substring(0, ex.Message.IndexOf(Environment.NewLine));
Assert.Equal(@"The required antiforgery cookie token must be provided.", trimmed);
}
[Fact]
public void ValidateTokens_FieldTokenMissing()
{
// Arrange
var httpContext = new DefaultHttpContext();
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity());
var cookieToken = new AntiforgeryToken() { IsCookieToken = true };
var tokenProvider = new DefaultAntiforgeryTokenGenerator(
claimUidExtractor: null,
additionalDataProvider: null);
// Act & assert
var ex = Assert.Throws<ArgumentNullException>(
() => tokenProvider.ValidateTokens(httpContext, cookieToken, null));
var trimmed = ex.Message.Substring(0, ex.Message.IndexOf(Environment.NewLine));
Assert.Equal("The required antiforgery request token must be provided.", trimmed);
}
[Fact]
public void ValidateTokens_FieldAndCookieTokensSwapped()
{
// Arrange
var httpContext = new DefaultHttpContext();
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity());
var cookieToken = new AntiforgeryToken() { IsCookieToken = true };
var fieldtoken = new AntiforgeryToken() { IsCookieToken = false };
var tokenProvider = new DefaultAntiforgeryTokenGenerator(
claimUidExtractor: null,
additionalDataProvider: null);
// Act & assert
var ex1 =
Assert.Throws<AntiforgeryValidationException>(
() => tokenProvider.ValidateTokens(httpContext, fieldtoken, fieldtoken));
Assert.Equal(
"Validation of the provided antiforgery token failed. " +
@"The cookie token and the request token were swapped.",
ex1.Message);
var ex2 =
Assert.Throws<AntiforgeryValidationException>(
() => tokenProvider.ValidateTokens(httpContext, cookieToken, cookieToken));
Assert.Equal(
"Validation of the provided antiforgery token failed. " +
@"The cookie token and the request token were swapped.",
ex2.Message);
}
[Fact]
public void ValidateTokens_FieldAndCookieTokensHaveDifferentSecurityKeys()
{
// Arrange
var httpContext = new DefaultHttpContext();
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity());
var cookieToken = new AntiforgeryToken() { IsCookieToken = true };
var fieldtoken = new AntiforgeryToken() { IsCookieToken = false };
var tokenProvider = new DefaultAntiforgeryTokenGenerator( var tokenProvider = new DefaultAntiforgeryTokenGenerator(
claimUidExtractor: null, claimUidExtractor: null,
additionalDataProvider: null); additionalDataProvider: null);
// Act & Assert // Act & Assert
var exception = Assert.Throws<AntiforgeryValidationException>( string message;
() => tokenProvider.ValidateTokens(httpContext, cookieToken, fieldtoken)); var ex = Assert.Throws<ArgumentNullException>(
Assert.Equal( () => tokenProvider.TryValidateTokenSet(httpContext, null, fieldtoken, out message));
@"The antiforgery cookie token and request token do not match.",
exception.Message); var trimmed = ex.Message.Substring(0, ex.Message.IndexOf(Environment.NewLine));
Assert.Equal(@"The required antiforgery cookie token must be provided.", trimmed);
}
[Fact]
public void TryValidateTokenSet_FieldTokenMissing()
{
// Arrange
var httpContext = new DefaultHttpContext();
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity());
var cookieToken = new AntiforgeryToken() { IsCookieToken = true };
var tokenProvider = new DefaultAntiforgeryTokenGenerator(
claimUidExtractor: null,
additionalDataProvider: null);
// Act & Assert
string message;
var ex = Assert.Throws<ArgumentNullException>(
() => tokenProvider.TryValidateTokenSet(httpContext, cookieToken, null, out message));
var trimmed = ex.Message.Substring(0, ex.Message.IndexOf(Environment.NewLine));
Assert.Equal("The required antiforgery request token must be provided.", trimmed);
}
[Fact]
public void TryValidateTokenSet_FieldAndCookieTokensSwapped_FieldTokenDuplicated()
{
// Arrange
var httpContext = new DefaultHttpContext();
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity());
var cookieToken = new AntiforgeryToken() { IsCookieToken = true };
var fieldtoken = new AntiforgeryToken() { IsCookieToken = false };
var tokenProvider = new DefaultAntiforgeryTokenGenerator(
claimUidExtractor: null,
additionalDataProvider: null);
string expectedMessage =
"Validation of the provided antiforgery token failed. " +
"The cookie token and the request token were swapped.";
// Act
string message;
var result = tokenProvider.TryValidateTokenSet(httpContext, fieldtoken, fieldtoken, out message);
// Assert
Assert.False(result);
Assert.Equal(expectedMessage, message);
}
[Fact]
public void TryValidateTokenSet_FieldAndCookieTokensSwapped_CookieDuplicated()
{
// Arrange
var httpContext = new DefaultHttpContext();
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity());
var cookieToken = new AntiforgeryToken() { IsCookieToken = true };
var fieldtoken = new AntiforgeryToken() { IsCookieToken = false };
var tokenProvider = new DefaultAntiforgeryTokenGenerator(
claimUidExtractor: null,
additionalDataProvider: null);
string expectedMessage =
"Validation of the provided antiforgery token failed. " +
"The cookie token and the request token were swapped.";
// Act
string message;
var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, cookieToken, out message);
// Assert
Assert.False(result);
Assert.Equal(expectedMessage, message);
}
[Fact]
public void TryValidateTokenSet_FieldAndCookieTokensHaveDifferentSecurityKeys()
{
// Arrange
var httpContext = new DefaultHttpContext();
httpContext.User = new ClaimsPrincipal(new ClaimsIdentity());
var cookieToken = new AntiforgeryToken() { IsCookieToken = true };
var fieldtoken = new AntiforgeryToken() { IsCookieToken = false };
var tokenProvider = new DefaultAntiforgeryTokenGenerator(
claimUidExtractor: null,
additionalDataProvider: null);
string expectedMessage = "The antiforgery cookie token and request token do not match.";
// Act
string message;
var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message);
// Assert
Assert.False(result);
Assert.Equal(expectedMessage, message);
} }
[Theory] [Theory]
[InlineData("the-user", "the-other-user")] [InlineData("the-user", "the-other-user")]
[InlineData("http://example.com/uri-casing", "http://example.com/URI-casing")] [InlineData("http://example.com/uri-casing", "http://example.com/URI-casing")]
[InlineData("https://example.com/secure-uri-casing", "https://example.com/secure-URI-casing")] [InlineData("https://example.com/secure-uri-casing", "https://example.com/secure-URI-casing")]
public void ValidateTokens_UsernameMismatch(string identityUsername, string embeddedUsername) public void TryValidateTokenSet_UsernameMismatch(string identityUsername, string embeddedUsername)
{ {
// Arrange // Arrange
var httpContext = new DefaultHttpContext(); var httpContext = new DefaultHttpContext();
@ -368,17 +417,21 @@ namespace Microsoft.AspNetCore.Antiforgery
claimUidExtractor: mockClaimUidExtractor.Object, claimUidExtractor: mockClaimUidExtractor.Object,
additionalDataProvider: null); additionalDataProvider: null);
// Act & Assert string expectedMessage =
var exception = Assert.Throws<AntiforgeryValidationException>( $"The provided antiforgery token was meant for user \"{embeddedUsername}\", " +
() => tokenProvider.ValidateTokens(httpContext, cookieToken, fieldtoken)); $"but the current user is \"{identityUsername}\".";
Assert.Equal(
@"The provided antiforgery token was meant for user """ + embeddedUsername + // Act
@""", but the current user is """ + identityUsername + @""".", string message;
exception.Message); var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message);
// Assert
Assert.False(result);
Assert.Equal(expectedMessage, message);
} }
[Fact] [Fact]
public void ValidateTokens_ClaimUidMismatch() public void TryValidateTokenSet_ClaimUidMismatch()
{ {
// Arrange // Arrange
var httpContext = new DefaultHttpContext(); var httpContext = new DefaultHttpContext();
@ -402,16 +455,21 @@ namespace Microsoft.AspNetCore.Antiforgery
claimUidExtractor: mockClaimUidExtractor.Object, claimUidExtractor: mockClaimUidExtractor.Object,
additionalDataProvider: null); additionalDataProvider: null);
// Act & assert string expectedMessage =
var exception = Assert.Throws<AntiforgeryValidationException>( "The provided antiforgery token was meant for a different " +
() => tokenProvider.ValidateTokens(httpContext, cookieToken, fieldtoken)); "claims-based user than the current user.";
Assert.Equal(
@"The provided antiforgery token was meant for a different claims-based user than the current user.", // Act
exception.Message); string message;
var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message);
// Assert
Assert.False(result);
Assert.Equal(expectedMessage, message);
} }
[Fact] [Fact]
public void ValidateTokens_AdditionalDataRejected() public void TryValidateTokenSet_AdditionalDataRejected()
{ {
// Arrange // Arrange
var httpContext = new DefaultHttpContext(); var httpContext = new DefaultHttpContext();
@ -428,21 +486,27 @@ namespace Microsoft.AspNetCore.Antiforgery
}; };
var mockAdditionalDataProvider = new Mock<IAntiforgeryAdditionalDataProvider>(); var mockAdditionalDataProvider = new Mock<IAntiforgeryAdditionalDataProvider>();
mockAdditionalDataProvider.Setup(o => o.ValidateAdditionalData(httpContext, "some-additional-data")) mockAdditionalDataProvider
.Returns(false); .Setup(o => o.ValidateAdditionalData(httpContext, "some-additional-data"))
.Returns(false);
var tokenProvider = new DefaultAntiforgeryTokenGenerator( var tokenProvider = new DefaultAntiforgeryTokenGenerator(
claimUidExtractor: null, claimUidExtractor: null,
additionalDataProvider: mockAdditionalDataProvider.Object); additionalDataProvider: mockAdditionalDataProvider.Object);
// Act & assert string expectedMessage = "The provided antiforgery token failed a custom data check.";
var exception = Assert.Throws<AntiforgeryValidationException>(
() => tokenProvider.ValidateTokens(httpContext, cookieToken, fieldtoken)); // Act
Assert.Equal(@"The provided antiforgery token failed a custom data check.", exception.Message); string message;
var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message);
// Assert
Assert.False(result);
Assert.Equal(expectedMessage, message);
} }
[Fact] [Fact]
public void ValidateTokens_Success_AnonymousUser() public void TryValidateTokenSet_Success_AnonymousUser()
{ {
// Arrange // Arrange
var httpContext = new DefaultHttpContext(); var httpContext = new DefaultHttpContext();
@ -467,14 +531,16 @@ namespace Microsoft.AspNetCore.Antiforgery
additionalDataProvider: mockAdditionalDataProvider.Object); additionalDataProvider: mockAdditionalDataProvider.Object);
// Act // Act
tokenProvider.ValidateTokens(httpContext, cookieToken, fieldtoken); string message;
var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message);
// Assert // Assert
// Nothing to assert - if we got this far, success! Assert.True(result);
Assert.Null(message);
} }
[Fact] [Fact]
public void ValidateTokens_Success_AuthenticatedUserWithUsername() public void TryValidateTokenSet_Success_AuthenticatedUserWithUsername()
{ {
// Arrange // Arrange
var httpContext = new DefaultHttpContext(); var httpContext = new DefaultHttpContext();
@ -499,14 +565,16 @@ namespace Microsoft.AspNetCore.Antiforgery
additionalDataProvider: mockAdditionalDataProvider.Object); additionalDataProvider: mockAdditionalDataProvider.Object);
// Act // Act
tokenProvider.ValidateTokens(httpContext, cookieToken, fieldtoken); string message;
var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message);
// Assert // Assert
// Nothing to assert - if we got this far, success! Assert.True(result);
Assert.Null(message);
} }
[Fact] [Fact]
public void ValidateTokens_Success_ClaimsBasedUser() public void TryValidateTokenSet_Success_ClaimsBasedUser()
{ {
// Arrange // Arrange
var httpContext = new DefaultHttpContext(); var httpContext = new DefaultHttpContext();
@ -530,10 +598,12 @@ namespace Microsoft.AspNetCore.Antiforgery
additionalDataProvider: null); additionalDataProvider: null);
// Act // Act
tokenProvider.ValidateTokens(httpContext, cookieToken, fieldtoken); string message;
var result = tokenProvider.TryValidateTokenSet(httpContext, cookieToken, fieldtoken, out message);
// Assert // Assert
// Nothing to assert - if we got this far, success! Assert.True(result);
Assert.Null(message);
} }
private static ClaimsIdentity GetAuthenticatedIdentity(string identityUsername) private static ClaimsIdentity GetAuthenticatedIdentity(string identityUsername)

View File

@ -6,6 +6,7 @@
"dependencies": { "dependencies": {
"Microsoft.AspNetCore.Antiforgery": "1.0.0-*", "Microsoft.AspNetCore.Antiforgery": "1.0.0-*",
"Microsoft.AspNetCore.Http": "1.0.0-*", "Microsoft.AspNetCore.Http": "1.0.0-*",
"Microsoft.AspNetCore.Testing": "1.0.0-*",
"Microsoft.Extensions.DependencyInjection": "1.0.0-*", "Microsoft.Extensions.DependencyInjection": "1.0.0-*",
"Microsoft.Extensions.WebEncoders": "1.0.0-*", "Microsoft.Extensions.WebEncoders": "1.0.0-*",
"Microsoft.NETCore.Platforms": "1.0.1-*", "Microsoft.NETCore.Platforms": "1.0.1-*",