The sample Identity project uses this to log out:
@if (Request.IsAuthenticated) {
using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })) {
@Html.AntiForgeryToken()
<ul class="nav navbar-nav navbar-right">
<li>@Html.ActionLink("Hello " + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" })</li>
<li><a href="javascript:document.getElementById('logoutForm').submit()">Log off</a></li>
</ul>
}
}
And the AccountController.LogOff()
action method has a [HttpPost]
.
The only reason I can think of to use a POST rather than a GET, is the [ValidateAntiForgeryToken]
. And I don't see the purpose to that, all we're doing is logging out.
Surely this is overkill? Why not use a regular GET link?
The reason is simple, anything that affects the state of the users session should never be a get action. Get actions should only ever be used for idempotent actions (ie, calling it multiple times has the same effect, and does not change state).
If you think about it, the reason should be obvious. Browsers are free to cache, or even pre-fetch get url's (and many modern browsers do just that). You wouldn't want the browser to accidentally log you out because it was pre-fetching a get link.
Now, that's less of an issue with the given code, as I don't think browsers will pre-fetch links that are associated with JavaScript (although I could be wrong).
A bigger issue is, if your logoff is a get action, then any unfiltered user-posted data could cause a logoff. For instance, suppose you have a forum on your site, and you allow images to be posted. Let's say someone posts an image where the src="http://url-to-log-off-the-site"
, this can cause a lot of havoc, since you can't even view the page to delete it without it logging you off.
Additionally, in the given example, there is a form field for the Anti-Forgery token, which would be encoded into the URL in a GET.. You wouldn't want to do that.
Your belief that using an anti-forgery token is overkill is because you don't understand what anti-forgery tokens are for. They're designed to prevent attackers from taking over your session... and you wouldn't want an attacker to log you out (don't be naïve enough to believe your site isn't important enough to attack, automated bots roam the internet and don't care about how important your site is).
Maybe the reason is that POST requests are not getting cached by default (if they don't have some particular headers) so this way when you try to logout you won't be getting a cached response.
all we're doing is logging out.
I don't think that logout is not important - lets say you are accessing your bank account from some public PC - I think that you want be 100% sure that when you perform a logout you will actually be loggedout.
Why would one HTTP method be overkill vs. another? Logging out affects server state and, therefore, the client posts it.
Looking at HTTP method definitions, there are security implications that recommend POST over GET:
Authors of services which use the HTTP protocol SHOULD NOT use GET based forms for the submission of sensitive data, because this will cause this data to be encoded in the Request-URI. Many existing servers, proxies, and user agents will log the request URI in some place where it might be visible to third parties. Servers can use POST-based form submission instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With