0

Currently, I am working on a web application, based on the roles we have to display the controls in the UI. Roles are stored in the DB, whenever the user logs in, by fetching the user Id, I will hit the DB and get the user role and store it in the cookie. So, for the next request, I will fetch the user role from the User.IsInRole() and proceed with the logic same will happens in the view. This entire thing is working fine with the single server but when it comes to load balancer, this behaving weirdly and intermittently it's giving issue, as User.IsInRole() is returning false sometime.

The code in my controller:

public ActionResult IsValidUser(string userName)
    {


        try
        {

                if (HttpContext!=null&& HttpContext.Request.Headers["username"] != null)
                {
                    userName = HttpContext.Request.Headers["username"];
                }

                //Get the roles by sending the user name
                userRole = _processor.GetUserRole(userName);

                UserViewModel user = new UserViewModel()
                {
                    UserName = userName,
                    Role = userRole
                };
                if (!string.IsNullOrEmpty(user.Role))
                {
                    FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, user.UserName, DateTime.Now, DateTime.Now.AddMinutes(2880), true, user.Role, FormsAuthentication.FormsCookiePath);
                    string hash = FormsAuthentication.Encrypt(ticket);
                    HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, hash);
                    if (ticket.IsPersistent)
                    {
                        cookie.Expires = ticket.Expiration;
                    }
                    if(Response!=null)
                    Response.Cookies.Add(cookie);

                    if (!string.IsNullOrEmpty(Request.Form["ReturnUrl"]))
                    {
                        return View("Error");
                    }
                    else
                    {

                        return RedirectToAction("Index");
                    }
                }
                else
                {
                    return View("Error")
                }
            }
            else
                return RedirectToAction("Search");
        }
        catch (Exception ex)
        {
                            return View("Error);
        }


    }

The code in Global.asax.cs

 protected void Application_AuthenticateRequest(Object sender, EventArgs e)
    {
        if (HttpContext.Current.User != null)
        {
            if (HttpContext.Current.User.Identity.IsAuthenticated)
            {
                if (HttpContext.Current.User.Identity is FormsIdentity)
                {
                    FormsIdentity id = (FormsIdentity)HttpContext.Current.User.Identity;
                    FormsAuthenticationTicket ticket = id.Ticket;
                    string userData = ticket.UserData;
                    string[] roles = userData.Split(',');
                    HttpContext.Current.User = new GenericPrincipal(id, roles);
                }
            }
        }
    }

the code in my controller to do the logic:

 public FileContentResult ViewAttachment(string attachmentName, int attachmentId)
    {

        if (ConfigurationManager.AppSettings["Environment"] != Constants.ProductionEnvironment ||
            (User.IsInRole(Constants.Administrator) || User.IsInRole(Constants.Contributor) || User.IsInRole(Constants.Member)))
        {
            //Logic here
            return File(bytes, mimeType);
        }
        else
        {
            _logger.WriteInformation("Not authorized");
            return File(bytes, mimeType);
        }
    }

I am not sure what mistake is there but this is not working in load balancer sometimes it is showing "User is not authorized" but in actual user is authorized. Is it because of cookies or load balancer? Any help would be appreciated. Thanks in advance.

Bhargav Konda
  • 169
  • 1
  • 9
  • You should remove all your authentication ... This look like anything but not secured... So why implement it :-) – Laurent Lequenne Feb 25 '19 at 10:56
  • @mjwills no I am not using client affinity – Bhargav Konda Feb 25 '19 at 11:06
  • @LaurentLequenne I am using for authorization, first time I will create a identity and store only roles to respecitive user and later retrive roles for coming requets. – Bhargav Konda Feb 25 '19 at 11:07
  • @mjwills I don't have any machineKey in my web.config – Bhargav Konda Feb 25 '19 at 11:10
  • 1
    Possible duplicate of [Adding machineKey to web.config on web-farm sites](https://stackoverflow.com/questions/3855666/adding-machinekey-to-web-config-on-web-farm-sites) – mjwills Feb 25 '19 at 11:17
  • @mjwills will give a try with machineKey in the web.config and update the thread. – Bhargav Konda Feb 25 '19 at 11:32
  • I mean how can you create a ticket, based only on the UserName passed in the headers ? This is not how it should work :-) – Laurent Lequenne Feb 25 '19 at 12:56
  • @LaurentLequenne The login is taken care by third-party page, for the first time the user will be redirected to the login page when he hits the URL if the login is a success then it redirects to the home controller of the actual application. Username is unique, it is like id and also I am retrieving the roles respective to that user, this is required for me to get the username and roles in the subsequent requests and I don't want to hit the DB every time to get the roles(stored in DB) that is the reason I created FormAuthenticationTicket, let me know if there is any better approach. – Bhargav Konda Feb 25 '19 at 14:23
  • So maybe you should change your external provider, he is the one that should create some ticket, or claim base token, or whatever encrypted… That you could reuse in your autorization mechanism. What you have now, makes no sense :) – Laurent Lequenne Feb 26 '19 at 16:49
  • @LaurentLequenne I cannot change the external provider as it's not in our control. And whatever I have done is not the right way, but I don't see any other approach for this scenario. I could look for sessions but that is something different concept in the load balancer as I have to change the settings for load balancer server where that is also not in our control. – Bhargav Konda Feb 27 '19 at 05:54
  • I tried with machine key in the config file and it's working thanks @mjwills – Bhargav Konda Mar 14 '19 at 07:38
  • Great to hear... – mjwills Mar 14 '19 at 11:09

0 Answers0