Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/Antiforgery/src/AntiforgeryOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,9 @@ public string FormFieldName
/// the X-Frame-Options header will not be generated for the response.
/// </summary>
public bool SuppressXFrameOptionsHeader { get; set; }

/// <summary>
/// Specifies whether to suppress load of antiforgery token from request body.
/// </summary>
public bool SuppressReadingTokenFromFormBody { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public async Task<AntiforgeryTokenSet> GetRequestTokensAsync(HttpContext httpCon
}

// Fall back to reading form instead
if (requestToken.Count == 0 && httpContext.Request.HasFormContentType)
if (requestToken.Count == 0 && httpContext.Request.HasFormContentType && !_options.SuppressReadingTokenFromFormBody)
{
// Check the content-type before accessing the form collection to make sure
// we report errors gracefully.
Expand Down
2 changes: 2 additions & 0 deletions src/Antiforgery/src/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
#nullable enable
Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.SuppressReadingTokenFromFormBody.get -> bool
Microsoft.AspNetCore.Antiforgery.AntiforgeryOptions.SuppressReadingTokenFromFormBody.set -> void
59 changes: 59 additions & 0 deletions src/Antiforgery/test/DefaultAntiforgeryTokenStoreTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,65 @@ public async Task GetRequestTokens_HeaderTokenTakensPriority_OverFormToken()
Assert.Equal("header-value", tokens.RequestToken);
}

[Fact]
public async Task GetRequestTokens_FormTokenDisabled_ReturnsNullToken()
{
// 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" },
});

var options = new AntiforgeryOptions
{
Cookie = { Name = "cookie-name" },
FormFieldName = "form-field-name",
HeaderName = "header-name",
SuppressReadingTokenFromFormBody = true
};

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

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

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

[Fact]
public async Task GetRequestTokens_FormTokenDisabled_ReturnsHeaderToken()
{
// 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");

var options = new AntiforgeryOptions
{
Cookie = { Name = "cookie-name" },
FormFieldName = "form-field-name",
HeaderName = "header-name",
SuppressReadingTokenFromFormBody = true
};

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

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

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

[Fact]
public async Task GetRequestTokens_NoHeaderToken_FallsBackToFormToken()
{
Expand Down