-
Notifications
You must be signed in to change notification settings - Fork 10.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow user to specify antiforgery request token source #51962
Allow user to specify antiforgery request token source #51962
Conversation
Thanks for your PR, @MaceWindu. Someone from the team will get assigned to your PR shortly and we'll get it reviewed. |
@@ -237,6 +329,7 @@ public async Task GetRequestTokens_ReadFormAsyncThrowsIOException_ThrowsAntiforg | |||
var ioException = new IOException(); | |||
var httpContext = new Mock<HttpContext>(); | |||
|
|||
httpContext.Setup(r => r.Features).Returns(new FeatureCollection()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mock context doesn't have Features
initialized. It is now needed to endpoint-level source configuration. Some mocked tests in other projects could probably fail for same reason as I run tests only for Antiforgery project
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] | ||
public class RequireAntiforgeryTokenAttribute(bool required = true) : Attribute, IAntiforgeryMetadata | ||
public class RequireAntiforgeryTokenAttribute(bool required = true, AntiforgeryRequestTokenSource? requestTokenSource = null) : Attribute, IAntiforgeryMetadata | ||
{ | ||
/// <summary> | ||
/// Gets or sets a value indicating whether the antiforgery token should be validated. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, it looks like documentation bug to me as there is no property setter to make it "Gets or sets"
Thanks for your PR, @MaceWindu. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall the change looks good, but needs more integration tests. It is hard to asses the correctness of the change based on the tests in DefaultAntiforgeryTokenStore and this kind of change warrants some tests here
We need to make sure we cover the following combos:
- HeaderOrBody (Token present / Token not present) -> (should already be covered by existing tests, point them on the PR if possible).
- HeaderOnly (Token present / Token not present) -> This is the new behavior, so we need to get a clear understanding that the implementation matches our expectations.
- We should only check the header during validation, but nothing should change for generation.
- Body only (Token present / Token not present) -> This should match the current semantics and skip the header altogether.
This also needs to go through API review @halter73.
Could you provide more details on expected tests? I don't see how
what kind of test you expect here?
|
Looks like this PR hasn't been active for some time and the codebase could have been changed in the meantime. |
@MaceWindu do you mind filling out and submitting the API proposal issue template for the new public |
/// Gets or sets a value indicating the locations to look for the antiforgery token in the request. | ||
/// If not set, <see cref="AntiforgeryOptions.RequestTokenSource"/> value used. | ||
/// </summary> | ||
public AntiforgeryRequestTokenSource RequestTokenSource |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we just make this nullable so anyone can determine the difference between unconfigured and explicitly HeaderOrFormBody
? Then we can go back to just using auto properties.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was initial design, but such types are not supported by metadata
@@ -39,16 +39,19 @@ public async Task<AntiforgeryTokenSet> GetRequestTokensAsync(HttpContext httpCon | |||
|
|||
var cookieToken = httpContext.Request.Cookies[_options.Cookie.Name!]; | |||
|
|||
// endpoint could override global request token source option | |||
var tokenSource = httpContext.GetEndpoint()?.Metadata.GetMetadata<RequireAntiforgeryTokenAttribute>()?.RequestTokenSourceValue ?? _options.RequestTokenSource; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if you have something like this?
[RequireAntiforgeryToken(RequestTokenSource = AntiforgeryRequestTokenSource.Header)]
public class MyController
{
[HttpPost]
[RequireAntiforgeryToken]
public IActionResult Post() { ... }
}
Based on this line, it looks like it will resolve the most specific RequireAntiforgeryTokenAttribute
which would be the one on the Post()
method and see that the RequestTokenSourceValue == null
and fall back to _options.RequestTokenSource
which is HeaderOrFormBody
when it ought to be using Header
as specified by the attribute on MyController
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will look into this scenario
@halter73, code updated to latest API design |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @MaceWindu!
Allow user to specify antiforgery request token source
Description
Currently default antiforgery implementation looks for antiforgery request token in header and when it is not found looks for token in request body (only for form requests).
This PR adds global and endpoint-level option to specify where to look for token. This is especialy useful when you want to prevent default antiforgery from reading request body as it could lead to:
Fixes #51912
Note that I've added both global and endpoint-level options. If we decide to keep only one, I will remove second.