5

I'm using the DropCreateDatabaseAlways Initializer so my database gets destroyed every time I start the application (at least I hope so). The funny thing is I still see myself as logged in. I get pass the Authorize attribute and can do dangerous stuff. This is probably because of leftover cookies from previous testing.

Registration/login part of my app is the MVC 4 Internet Application template untouched. Shouldn't ASP.NET check the cookie values against users saved in the DB? WebSecurity.IsAuthenticated returns true and WebSecurity.CurrentUserName returns the name. The only thing working as expected is WebSecurity.CurrentUserId which returns -1. I'm a newbie so I can only guess this is because UserId isn't stored in the cookie and must be retrieved from the database.

Am I right? If so, does it mean I should always use WebSecurity.CurrentUserId to determine whether a user is logged in? WebSecurity.IsAuthenticated and User.Identity.IsAuthenticated seem pretty useless in that case. I can delete a user's account and he or she remains unaffected. What should be done differently if I am wrong?

Konrad Gadzina
  • 3,407
  • 1
  • 18
  • 29
Matt Ricks
  • 51
  • 3
  • I have to ask. Does it really matter? In production, how often will you be throwing away the database? Never? So what's the issue? If you're worried, don't make the cookie persistent (remove any checkbox that keeps them logged in, and set false for persistent cookie). Yes, you can delete them and if they are currently logged in they can still have access, but as soon as they close their browser they can't log in again. – Erik Funkenbusch Apr 14 '13 at 17:54

6 Answers6

1

There will be a small window where if a user is deleted and they are still logged in that they can still access the site. Since most actions require a validate user id, you can simply throw an excpetion and log the user out.

Normally the database does not get blown away on each build, so I'm guessing this is not a use case SimpleMembership was coded for. You can of course check for this. I'll make another assumption that you are not closing your browser when you rebuild the site and deploy the new database. In a real world scenario these things just don't happen. The database is never blown away and the user id is never lost.

Generally once you've logged in the user, the user is not authenticated anytime after that (unless they have logged out, or the session has expired). That's the point of login. The authentication cookie is an indication that the authentication happened and was successful. The assumption going forward is the user has access to your site and is not reauthenticated.

Chuck Conway
  • 16,287
  • 11
  • 58
  • 101
  • It just seems a security flaw to me that (Simple)Membership doesn't query the database and blindly uses username extracted from the authentication cookie. What's that good for if the user may have already been deleted and since I need user id anyway? – Matt Ricks Apr 14 '13 at 19:18
  • 1
    @MattRicks Its an assumption that once you've been authenticated the account is valid. In all the systems I've worked on I've never seen a case where the user was logged in when an account was deleted. Not to say it can't happen, it's an edge case. Why is it a bad thing to use the user id from the auth cookie? The auth cookie is encrypted specific to that machine. It trusts the cookie, because it set the cookie. – Chuck Conway Apr 15 '13 at 04:28
  • 2
    Well I think the IsAuthenticated method should work like this: 1. check the cookie values 2. query the DB for user id 3. return whether the user has the auth cookie AND exists. It looks like I'm the only one having problem with the current version. :) – Matt Ricks Apr 15 '13 at 11:51
  • Fortunately, the WebSecurity class has other methods and properties more suitable for my application. I just have to replace the "problematic" default authentication call with the right one. – Matt Ricks Apr 15 '13 at 12:47
1

If you want to realiably check whether a user has not been deleted, you just have to consult the database.

Note that users and administrators work concurrently. This means that a user can be deleted just a second after he has been authenticated. A cookie can be then even one or two seconds old (!) and the user could probably have been just deleted.

In a most pessimistic scenario, a user types a valid username and password and is succesfully logged in and get the "sorry, your account has been deleted" just one request later (because the account has really just been deleted).

Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
1

As long as the authentication session remains open (i.e. browser now closed), the session cookie remains active and MVC assumes that the user is still valid.

Remove the cookie by using FormsAuthentication.LogOff() if the user is authenticated (User.Identity.IsAuthenticated == true) and there's no valid user in UserTable (WebSecurity.CurrentUserId == -1).

Stephen Reindl
  • 5,659
  • 2
  • 34
  • 38
1

I had the same issue, but solved it by specifying the required role(s) in the Authorize attribute. As soon as you do this, it start getting to the database and fails with the "user does not exist" error, which is what you want.

[Authorize(Roles = "Customer")]
public class DashboardController : Controller
auroceo
  • 11
  • 1
0

In normal case adding Session.Abandon(); to to your LogOff action in AccountController would do the job of clearing session:

public ActionResult LogOff()
{
    FormsAuthentication.SignOut();
    Session.Abandon();

    return RedirectToAction("Index", "Home");
}

So I think you can try adding Session.Abandon(); in init code, where you use DropCreateDatabaseAlways to clear session each time.

Konrad Gadzina
  • 3,407
  • 1
  • 18
  • 29
0
  • The ticket issuing time is usually encrypted within the authentication cookie then you can use it to require re-authentication to sensitive areas (inbox/billing etc.) if more than X time passed since login.

  • If you insist on invalidating all current auth tickets upon application changes (i.e database/configuration) you can change this settings in your web.config:

    <machineKey validationKey="..." decryptionKey="" />
    
haim770
  • 48,394
  • 7
  • 105
  • 133