views:

1672

answers:

6

This seems like a pretty stupid question, but I'm trying to figure out the best way to do this. Would you simply redirect to a /Logout page and have the controller call the FormsAuthentication.SignOut function?

That was my first thought, but then I wondered if it could be abused by third party websites. Let's say someone just decides to post a link to your /Logout page. The user would get signed out of your application. Is there a good way to prevent that?

A: 

You should look for a cookie or something that identifies the client as the true user.

SaaS Developer
How would that help? The user would still be logged out when they clicked the link.
Kevin Pang
Doesn't this problem exist with any web application, built with any language, where logging out involves going to some kind of logout page? You could check the referrer and make sure that the user came from the same domain, but that's not always reliable.
Mun
A: 

This is what I use.

public ActionResult Logout()
{
    FormsAuth.SignOut();
    return RedirectToAction("Index", "Home");
}

Seems to work fine.

Third party websites are only going to log themselves out. So they wouldn't be achieving anything different from actually clicking Logout.

Schotime
So let's say your app is located at http://url.com and your logout page is http://url.com/logout. If a third party website posted a link to http://url.com/logout, any users that are logged into your app that click that link will log themselves out, right?
Kevin Pang
Can you check to see if it is a postback in MVC? if so, then logout, otherwise just redirect to the index view?
Mark
@kevin, Only the 3rd party app would be logged out. No users currently using your application would be logged out until they clicked it themselves.@Mark You could allow only GET requests to the controller.
Schotime
+1  A: 

If you are concerned about a user getting accidentally logged out of you application through the use of a malicious link, you can check the Referrer to make sure that the logout is coming from your site (or is NULL in the case where the user simply types the URL in).

I actually don't worry about this since logging someone out is annoying but not necessarily a security risk.

tvanfosson
My thoughts as well. While annoying, it's not a security risk.
Mike Brown
I agree, I don't think maliciously logging people out is a big problem. And they would have had to had left your site anyway to go to the other site so having to log back in when they return shouldn't be a problem.
Craig
Referrers can be spoofed way to easily. Check the CSRF answer.
Chuck
My last point was that while annoying it's not particularly egregious. I regard a spoofed Referer in this case to be innocuous and wouldn't put much effort into verifying that the logout is coming from the correct host. It goes without saying that it should be a GET request and not be allowed to modify any data directly.
tvanfosson
+2  A: 

Such a malicious link would be an example of a class of security vulnerabilities known as cross site request forgery, CSRF. A logout link is relatively harmless, but a remote site could set up a number of hidden forms and post them to your site to perform any action possible through POST.

The most common counter-measure is to include a challenge, a random hidden value in each form, and then check for that value. Checking the referer header could work, but note that some browsers don't send referer at all.

Read more: http://en.wikipedia.org/wiki/Cross-site_request_forgery

jakber
+1  A: 

The new ASP.net MVC Beta contains an AccountController, which may be worth looking at, as it essentially implements everything from Registration to Login/Logout to Forgot Password functionality. Not sure how good it is, but a good starting Point for sure.

Michael Stum
BTW, Mike, congrats on being the first CrackOverflow addict to break 10k.
Will
A: 

Derive from ActionResult

public class LogoutResult : ActionResult
{
 private readonly IAuthenticationService _authenticationService;
 private readonly IWebContext _context;

 public LogoutResult(IAuthenticationService authenticationService, IWebContext context)
 {
  _authenticationService = authenticationService;
  _context = context;
 }

 public override void ExecuteResult(ControllerContext context)
 {
  _authenticationService.Logout();
  _context.Abandon();
  _context.Redirect("~/");
 }
}
Matt Hinze