We have a website that uses MVC3 and a custom authentication method that does not rely on forms authentication at all -- at least from what I can tell. In web.config we set
<authentication mode="None"></authentication>
and we never use/set HttpContext.User anywhere in code. The problem is when using #Html.AntiForgeryToken() in some cases the user gets this error message:
A required anti-forgery token was not supplied or was invalid
We centralize all anti-forgery checks in OnAuthorization with this code:
if (String.Compare(filterContext.HttpContext.Request.HttpMethod, "post", true) == 0)
{
var forgery = new ValidateAntiForgeryTokenAttribute();
forgery.OnAuthorization(filterContext);
}
That is where the exception occurs. We have defined a machineKey in web.config to prevent new keys being generated when the application pool recycles. This did not fix the problem.
Next we thought that maybe the client's browser is not sending cookies. We started logging cookies and noticed that in some cases the RequestVerificationToken_Lw cookie is sent, but in others is not -- even though other cookies, like the ones made by Google Analytics, are sent along just fine. Could it be something in the browser is stripping out some cookies and leaving others in?
It seems like the anti-forgery token depends on forms authentication. Is this the case? Any way to keep using the AntiForgeryToken when not using forms authentication in a reliable way. Keep in mind that the method I described above works for more than 90% of cases, but we can't pinpoint why it doesn't work for some people.
Thoughts?
Thanks!
Do some users have this issue all the time? Or just some of the time? Also, does it work for some of the methods ALL the time or is it inconsistent for the same action method? Do you have any ajax calls? The default anti-forgery token implementation does not handle AJAX calls. But you can write some custom code to get it to work
Are you adding the antiforgery token inside of the form? The antiforgery token is stored on the client via a hidden HTML element so and not as a cookie. The other question would be what browser version are they using? Are can the upgrade to the latest?
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()...
Related
I am curious if anyone has a solution to this unique situation as I have a solution currently, though I feel it is not the most optimal.
The Situation.
I have built an MVC style web application that talks to a web API through http (authenticating via JWT). My web application is secured by appending authorization to its view controllers and redirecting to a Microsoft login endpoint - then directing back to the view where whichever given controller/function handles the request, connects to the API, appends data to the view, etc.
Preferably I would like to use JQuery/Ajax to submit http requests client-side and update a given view with whatever data the user may wish to see relative to the webpage they're on. This way I could control exactly what the user should see landing on the page any which way and submitting requests from web app to API. Also would enable better continuity between requests as there isn't actually a full refresh of the view. All in all it is my line of thought that this execution would lead to a nice user experience.
The Problem.
So the big issue that I have had to circumvent is CORS Policy. I initially attempted to use JS just as I said above but requests would be redirected to the login endpoint and blocked due to there being no CORS header appended to the request.
'So include a policy in your application and append an authorized header to your Ajax outgoing request' you might say, well... you cannot override CORS security around Microsoft's login endpoint.
My Solution.
What I have done simply instead is create HTML Forms around fields the user would pick and chose to specify what data they wanted from the API. Then carry over input data to the returned view via 'ViewData'
and using razor pages of course I can actually initialize JS variables via C# input.
Side Note
I use JS to transform the API data into graphs for the user to see. I am doing this with a JavaScript Library.
My Question to you.
This all leads me to ask then, is there a way to dynamically update a view without using JS? I require a method that can hit the login redirect without being blocked because the request initiated client-side.
Every solution I am aware in some way, shape, or form utilizes JS to make the request. So I am at a loss for how to truly get the functionality I am after without having my requests get blocked due to CORS Policy.
Thanks in advance y'all.
I'm trying to better understand the mechanism for how Spring CSRF protection works. Suppose I have a site https://example.com/ where people can vote on candidates. Users can also exchange messages. I also have a user logged in, and another user that sends her a message saying to click on the link https://example.com/vote/candiate/30.
If a user clicks on this link, won't the browser send both the CSRF token and the session ID for the logged in user, thereby bypassing the CSRF protection check?
The reason a link is usually not a problem regarding CSRF is that CSRF is only an issue when the request changes something. A link (a GET request) should not change anything. If it does, like in your example it adds a vote to the candidate I suppose, any link from an external origin (a different website) would also be able to exploit "normal" CSRF by just linking to that url.
The problem in the example is not that CSRF protection is inadequate in Spring, the problem is that voting in this case is a GET request, and GETs are not usually protected against CSRF by design. The solution is to change the vote request to a POST, which would then be protected against CSRF (and which would also be more RESTful btw).
Main idea :
When request is submitted, the server received special cookie and waits for defined value in this cookie. If this value will be differet , the request should fail.
So, if service returns form for moving money between accounts, this form includes parameter, that expected to receive when form is submitted, and if data would be sent without this parameter, request wouldn't be proccessed
I'm developing an ASP.NET MVC application and I'm planing to protect each non GET request (POST, PUT, DELETE, etc...) with AntiForegeryToken.
I've implemented an extension of the classical AntiForgery verification based on the [__RequestVerificationToken] sent in the header. This because most of my calls are async ($.ajax()) and it turns out easier for me to send the hidden field value that way.
Does it make sense to put one single #Html.AntiForgeryToken() in the _Layout.cshtml (template for all pages) and always refer to that one only ?
I've tryed to understand what wolud be different beteen this option and putting it in each form (that I don't use much since my requests are pretty much all async), but I haven't.
Can anyone clear this to me ?
Thanks
Lorenzo
You can put it in your _Layout.cshtml and generate a single token when the page is rendered, that's fine.
While there is a very slight security benefit of using a different token for every request, if your token has enough entropy (and the standard token generated by #Html.AntiForgeryToken() does), then it is practically infeasible for an attacker to guess the token even during the time of a user session. So one token per user session is still considered secure in most cases.
Actually, trying to use a new token for each request leads to all kinds of bugs in a Javascript heavy application, because the browser needs a non-neglectible time to actually change things like a cookie value or to send a request, and frequent ajax requests will lead to a race condition and you will have hard to debug bugs around token mismatches.
ASP.NET MVC still focuses on traditional form-based applications in this regard, and while you can use it to prevent CSRF in modern Javascript-heavy apps with some tweaks (like a custom attribute to actually verify a token sent in request headers), you do have to write some custom code to do that. Hopefully Microsoft will add built in support in future versions.
UPDATE
After implementing the solution with #Html.AntiForgeryToken() directly in Template page (_Layout.cshtml) I found out a possible problem bound to the use of custom Claims. The problem happens during re-validation of UserIdentity. As a reference I'll leave the link to another post in which I've been dealing with that and added there the wotrkaround for those who choose the same implementation.
Custom Claims lost on Identity re validation
Hope it helps !
I have a page on domain A which includes a javascript from from domain B. The script loads a form from domain A with Ajax and posts it back to A.
The form got rejected by Yesod because of missing session variable which resides in a cookie and isn't transmitted on Ajax request because of that.
Can Yesod's session mechanism be made work in such a situation?
I was given an answer by Michael Shoyman, the author of Yesod. The easiest way in my case is to disable CSRF protection for that particular form. There is an api function for that.
http://hackage.haskell.org/packages/archive/yesod-form/1.1.4.1/doc/html/Yesod-Form-Functions.html#v:runFormPostNoToken
I am trying to do some screen scraping accessing a forms authenticated website. I was doing some tests on an asp.net forms authenticated site that I built and it worked just great. When I tried the real site I realized it was using some kind of an Oracle forms authentication (a fiddler showed a call to a dll instead of an html file. I suppose this dll provides the html result). What I see in fiddler is:
https://{domain}/access/oblix/apps/webgate/bin/webgate.dll
The rest of the call seems similar, cookie, user name and password, just like in the regular forms authentication.
Any idea on how to crack this type of request (to a dll instead of an html)?
(By the way, the result I get is some kind of an Oracle error).
With Forms Authentication the webserver issues the client with a cookie that is used to verify the client in future subsequent requests (HTTP Basic and Digest authentication requires the client to post the "WWW-Authorization" header on every request). Are you persisting your cookies between requests?
The file extension of the url is not important to how you make your request.
It sounds like your script needs to make a request identical to the ajax request made by your browser (and shown in fiddler).