0

I'm currently having a code in the Login action, so when the user login, it will pull some data from the database and store in a Session variable.

public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (!ModelState.IsValid)
    {
        return View(model);
    }

    var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: true);
    switch (result)
    {
        case SignInStatus.Success:
            {
                using (var db = new somedbContext())
                {
                    //do some query here

                    System.Web.HttpContext.Current.Session["userDepartment"] = departmentID; 
                }

                return RedirectToLocal(returnUrl);
            }    
    }
}

This works just fine if the user actually goes through the Login process. However, if the user tries to "login" with other means, such as using cookie (by remember me), or some browsers do save the credentials, or using a third party logins etc., this will not work anymore.

Where should I write the code and assign value to the Session so that regardless of where the user login from, it will go through the code?

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466
C.J.
  • 3,409
  • 8
  • 34
  • 51
  • 1
    This kind of stuff is why I just like to avoid using the session altogether. – Casey Jan 29 '15 at 17:40
  • Agreed, @emodendroket. It's especially thorny if you're using clusters. Maybe you ought to post an answer (maybe one already exists) for alternative approaches. – Jacob Jan 29 '15 at 18:15

1 Answers1

4

You can put the logic to lazy-initialize that session variable in a global filter based on IAuthorizationFilter.

The filter could be something like this:

public class SetDepartmentFilter : IAuthorizationFilter 
{
    public void OnAuthorization(AuthorizationContext filterContext)
    {
        var userInfo = GetUserInfo(filterContext);
        if (userInfo.IsAuthorized)
        {
            filterContext.HttpContext.Session["userDeparment"] = userInfo.Department;
        }
    }

    private UserInfo GetUserInfo(AuthorizationContext filterContext)
    {
        // TODO: see if authorized, get department, etc.
    }
}

Somewhere in your application startup:

GlobalFilters.Filters.Add(new SetDepartmentFilter());
Jacob
  • 77,566
  • 24
  • 149
  • 228
  • Can you please elaborate a little bit more – C.J. Jan 29 '15 at 17:06
  • Do you have any link/tutorial on how to implement this? – C.J. Jan 29 '15 at 17:28
  • How do I check if the user is Authorized? I cannot access any of the methods such as `User.Identity.GetuserId` etc. – C.J. Jan 29 '15 at 17:59
  • You can get most of what you need from `filterContext.HttpContext`, for example, `filterContext.HttpContext.User`. You'll need to make sure this filter runs _after_ whatever process establishes the user. – Jacob Jan 29 '15 at 18:12