I have an MVC app using Forms Authentication, and I'm getting 404 errors. What's happening is the user happens to be submitting a form to a POST-only action when their authentication has timed out, and they are redirected to the login page. After login they are redirected back to the original URL using GET, which will result in a 404 error as the action is POST-only.
I have two questions:
My idea to get around this is to somehow detect whether the action being redirected to is a POST-only action, and redirect to the homepage instead. How would I go about doing that?
Ideally, the app would remember the values posted, and submit them to the original URL via POST, but I have no idea how I would bypass Forms Authentication to do this, and I suspect this would be open to security vulnerabilities. Is this a good idea and if so how could it be done?
I created an action filter as a result of the responses above, I'll leave it here for posterity. It passes any specified parameters from the attempted action through to the redirect action.
To use, simply replace the
HttpPost
filter on the relevant action withHttpPostOrRedirect
thus:A simple fix would be to create a GET only action with the same name as the POST only one, that justs redirects to the homepage. Creating a solution that will resume a form post after a log in would be quite a lot of work for minimal gain.
UPDATE:
Regarding the amount of work it would be to create all of these GET actions.. A more elegant option would be to create an attribute specifically for this scenario, something named like
HttpPostOrRedirectAttribute
, that you could use to decorate these post only actions rather than use theHttpPostAttribute
. The behaviour of this would be that it accepts posts, but rather than throwing 404 performs redirects for other verbs.Having encountered exactly this problem we create [HttpGet] actions for the Posts that redirected to the Index; the user loses their entered data - so it isn't great - but it was the quick way round it for us.
Here's improved version of @stusherwin answer with support of ValidateAntiForgeryToken and MVC areas.
Likely your POST Actions have an ValidateAntiForgeryToken attribute to prevent CSRF attacks. In this case ValidateAntiForgeryToken filter will always be executed first since it is Authorization Filter. So we need to make HttpPostOrRedirectAttribute an Authorization Filter as well. Otherwise, exception will be thrown that anti forgery token is not found.
Another improvement is to add redirects to MVC Areas
Here's an example how to use it together with ValidateAntiForgeryToken attribute and redirect to Admin area:
How about making a GET action that redirects to the page that contains the original form?
You coudl add some extra info to the ModelView data, to indicate that a message should be displayed to the user. This message should say something like this...
"You submitted this form whilst logged out - now that you've logged in, do you wish to continue the submission"
Or, if you really wanted to, the extra information in the ModelViewData could cause the form to be automatically submitted.
As you say, this is quite a bit of extra work, if you have lots of form pages, but there ought to be some way of encapsulating the behaviour for re-use.