Skip to content
This repository has been archived by the owner on Nov 22, 2018. It is now read-only.

Commit

Permalink
Change priority for request token source lookup. Header token now tak…
Browse files Browse the repository at this point in the history
…es priority over form field token.
  • Loading branch information
kichalla committed May 19, 2016
1 parent f65c3db commit 3595452
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,21 +44,23 @@ public async Task<AntiforgeryTokenSet> GetRequestTokensAsync(HttpContext httpCon

var cookieToken = httpContext.Request.Cookies[_options.CookieName];

// We want to delay reading the form as much as possible, for example in case of large file uploads,
// request token could be part of the header.
StringValues requestToken;
if (httpContext.Request.HasFormContentType)
if (_options.HeaderName != null)
{
requestToken = httpContext.Request.Headers[_options.HeaderName];
}

// Fall back to reading form instead
if (requestToken.Count == 0 && httpContext.Request.HasFormContentType)
{
// Check the content-type before accessing the form collection to make sure
// we report errors gracefully.
var form = await httpContext.Request.ReadFormAsync();
requestToken = form[_options.FormFieldName];
}

// Fall back to header if the form value was not provided.
if (requestToken.Count == 0 && _options.HeaderName != null)
{
requestToken = httpContext.Request.Headers[_options.HeaderName];
}

return new AntiforgeryTokenSet(requestToken, cookieToken, _options.FormFieldName, _options.HeaderName);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Internal;
Expand Down Expand Up @@ -99,40 +100,44 @@ public async Task GetRequestTokens_CookieIsEmpty_ReturnsNullTokens()
}

[Fact]
public async Task GetRequestTokens_NonFormContentType_HeaderDisabled_ReturnsNullToken()
public async Task GetRequestTokens_HeaderTokenTakensPriority_OverFormToken()
{
// Arrange
var httpContext = GetHttpContext("cookie-name", "cookie-value");
httpContext.Request.ContentType = "application/json";

// Will not be accessed
httpContext.Request.Form = null;
httpContext.Request.ContentType = "application/x-www-form-urlencoded";
httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues>
{
{ "form-field-name", "form-value" },
}); // header value has priority.
httpContext.Request.Headers.Add("header-name", "header-value");

var options = new AntiforgeryOptions()
{
CookieName = "cookie-name",
FormFieldName = "form-field-name",
HeaderName = null,
HeaderName = "header-name",
};

var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options));

// Act
var tokenSet = await tokenStore.GetRequestTokensAsync(httpContext);
var tokens = await tokenStore.GetRequestTokensAsync(httpContext);

// Assert
Assert.Equal("cookie-value", tokenSet.CookieToken);
Assert.Null(tokenSet.RequestToken);
Assert.Equal("cookie-value", tokens.CookieToken);
Assert.Equal("header-value", tokens.RequestToken);
}

[Fact]
public async Task GetRequestTokens_FormContentType_FallbackHeaderToken()
public async Task GetRequestTokens_NoHeaderToken_FallsBackToFormToken()
{
// Arrange
var httpContext = GetHttpContext("cookie-name", "cookie-value");
httpContext.Request.ContentType = "application/x-www-form-urlencoded";
httpContext.Request.Form = FormCollection.Empty;
httpContext.Request.Headers.Add("header-name", "header-value");
httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues>
{
{ "form-field-name", "form-value" },
});

var options = new AntiforgeryOptions()
{
Expand All @@ -148,7 +153,7 @@ public async Task GetRequestTokens_FormContentType_FallbackHeaderToken()

// Assert
Assert.Equal("cookie-value", tokens.CookieToken);
Assert.Equal("header-value", tokens.RequestToken);
Assert.Equal("form-value", tokens.RequestToken);
}

[Fact]
Expand Down Expand Up @@ -180,7 +185,7 @@ public async Task GetRequestTokens_NonFormContentType_UsesHeaderToken()
}

[Fact]
public async Task GetRequestTokens_NonFormContentType_NoHeaderToken_ReturnsNullToken()
public async Task GetRequestTokens_NoHeaderToken_NonFormContentType_ReturnsNullToken()
{
// Arrange
var httpContext = GetHttpContext("cookie-name", "cookie-value");
Expand All @@ -207,7 +212,7 @@ public async Task GetRequestTokens_NonFormContentType_NoHeaderToken_ReturnsNullT
}

[Fact]
public async Task GetRequestTokens_BothFieldsEmpty_ReturnsNullTokens()
public async Task GetRequestTokens_BothHeaderValueAndFormFieldsEmpty_ReturnsNullTokens()
{
// Arrange
var httpContext = GetHttpContext("cookie-name", "cookie-value");
Expand All @@ -231,35 +236,6 @@ public async Task GetRequestTokens_BothFieldsEmpty_ReturnsNullTokens()
Assert.Null(tokenSet.RequestToken);
}

[Fact]
public async Task GetFormToken_FormFieldIsValid_ReturnsToken()
{
// Arrange
var httpContext = GetHttpContext("cookie-name", "cookie-value");
httpContext.Request.ContentType = "application/x-www-form-urlencoded";
httpContext.Request.Form = new FormCollection(new Dictionary<string, StringValues>
{
{ "form-field-name", "form-value" },
});
httpContext.Request.Headers.Add("header-name", "header-value"); // form value has priority.

var options = new AntiforgeryOptions()
{
CookieName = "cookie-name",
FormFieldName = "form-field-name",
HeaderName = "header-name",
};

var tokenStore = new DefaultAntiforgeryTokenStore(new TestOptionsManager(options));

// Act
var tokens = await tokenStore.GetRequestTokensAsync(httpContext);

// Assert
Assert.Equal("cookie-value", tokens.CookieToken);
Assert.Equal("form-value", tokens.RequestToken);
}

[Theory]
[InlineData(true, true)]
[InlineData(false, null)]
Expand Down

0 comments on commit 3595452

Please sign in to comment.