11

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?

flipdoubt
  • 13,897
  • 15
  • 64
  • 96
h bob
  • 3,610
  • 3
  • 35
  • 51
  • Also: http://forums.asp.net/t/1822324.aspx?Logout+action+http+GET+or+POST+ – Patrick Hofman Sep 07 '14 at 15:42
  • 2
    Nice @PatrickHofman :) In that link, [this seems to say a lot](https://twitter.com/Nick_Craver/status/296281730984316928) – EdSF Sep 07 '14 at 16:29
  • Not sure it's a duplicate within the context of Identity API. That thing is so poorly documented (or not at all) that everything seems more complicated than necessary. I've never considered this question before, and assumed it had something to do with the API rather than good web dev practice. – h bob Sep 07 '14 at 17:20

3 Answers3

13

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).

Erik Funkenbusch
  • 92,674
  • 28
  • 195
  • 291
  • I do understand what the token is for. I wasn't implying to simply change to GET. I implied to drop the entire code and replace with a link. – h bob Sep 07 '14 at 17:06
  • However the part in your answer about using a GET resulting in automatically being logged out (e.g. because of prefetching) makes sense, and I do agree with it. – h bob Sep 07 '14 at 17:07
1

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.

Alex Art.
  • 8,711
  • 3
  • 29
  • 47
1

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.

flipdoubt
  • 13,897
  • 15
  • 64
  • 96
  • 2
    The first part of your answer seems to say that there's no qualitative value to one HTTP method over another, but then you go on to list a qualitative value. Those seem to be conflicting statements. – mason Sep 07 '14 at 14:46
  • What is "wrong" or "too much" or "overkill" about using the POST method? Especially when changing server state. How is that conflicting? – flipdoubt Sep 07 '14 at 14:48
  • The first sentence in my answer is not meant to be snarky. I honestly do not understand how one HTTP method would be overkill where another would not. – flipdoubt Sep 07 '14 at 14:57
  • It's not about snark, and it's not about your first sentence. Please re-read my comment. You imply that it's wrong to ascribe a qualitative value to an HTTP method, but then you go on to list a qualitative difference. That is conflicting, and I think you should remove the second sentence to remove that conflict. – mason Sep 07 '14 at 15:00
  • It is removed. Thanks. – flipdoubt Sep 07 '14 at 15:02
  • Your reasoning is sensible and accurate, but I was looking for a practical reason to use the one vs the other. Most programmers don't obsess about the theory/philosophy of things, or run to the spec when there's a concern. The real reason, is the one by @PatrickHofman, which is that hiding the logout behind a form will prevent auto-logout by over-eager browsers. Everything else is secondary. – h bob Sep 07 '14 at 17:11