Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Web Development
  3. ASP.NET
  4. How to manage a combined role + organization security in MVC?

How to manage a combined role + organization security in MVC?

Scheduled Pinned Locked Moved ASP.NET
csharpasp-netsecurityvisual-studiocom
4 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • F Offline
    F Offline
    F Margueirat
    wrote on last edited by
    #1

    Hi everyone I am fairly new to MVC and I've only done simple projects without security before. I am now working in a new, more complex project that requires a security model based on role + organization. The authorization will be based on Windows user. Once the users are validated, they will be marked as working with their default organization, but the can change the organization at any time. We are imagining a drop-down with the organizations the user belong to, and stored the current one as a session variable. The simplest part of the projects consists of several CRUDs. We have users that are either viewers or editors in these CRUDs, but their role may vary depending on the organization they are working on. E.g. for the "Branches" table, User "Peter" may be an editor for organization 1 and a viewer for organizations 2 and 3. If I ignore the organization, I can easily manage the security by extending System.Web.Security.RoleProvider and handling the logic within that class. I believe I could read the current organization from the session variable (haven't tried that yet) in order to add that to the class logic, but I'm pretty sure there must be a better solution. Can anyone suggest a better solution? Ideally it should be following the ASP.NET System.Web.Security model. Any Visual Studio integrated framework that makes this security handling easier is also very welcomed. Thank you

    J 1 Reply Last reply
    0
    • F F Margueirat

      Hi everyone I am fairly new to MVC and I've only done simple projects without security before. I am now working in a new, more complex project that requires a security model based on role + organization. The authorization will be based on Windows user. Once the users are validated, they will be marked as working with their default organization, but the can change the organization at any time. We are imagining a drop-down with the organizations the user belong to, and stored the current one as a session variable. The simplest part of the projects consists of several CRUDs. We have users that are either viewers or editors in these CRUDs, but their role may vary depending on the organization they are working on. E.g. for the "Branches" table, User "Peter" may be an editor for organization 1 and a viewer for organizations 2 and 3. If I ignore the organization, I can easily manage the security by extending System.Web.Security.RoleProvider and handling the logic within that class. I believe I could read the current organization from the session variable (haven't tried that yet) in order to add that to the class logic, but I'm pretty sure there must be a better solution. Can anyone suggest a better solution? Ideally it should be following the ASP.NET System.Web.Security model. Any Visual Studio integrated framework that makes this security handling easier is also very welcomed. Thank you

      J Offline
      J Offline
      jkirkerx
      wrote on last edited by
      #2

      I'm no expert at this by far. But I'll mention the HttpContext. It has a lifespan of one cycle and is stateless. So I made a Attribute that you decorate the controller ActionResult with. It runs run before the ActionResult is fired, and passes everything downstream. Basically it's session free so you don't have to worry about restarts or what server you hit. I do remember this being a little buggy, in terms of having to erase the cookie a couple of times when exiting debug and starting again, but I think I fixed it.

      [AdminCheck]
      public IActionResult SomeEditor()

      The AdminCheck reads the cookie with special data in it, and if the user authenticates, it creates a new HttpContext.User using a GenericIdentity and GenericPrincipal I wrote this for .Net Core

      [AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
      public class AdminCheckAttribute : ActionFilterAttribute, IActionFilter
      {
      public override void OnActionExecuting(ActionExecutingContext filterContext)
      {
      var controller = filterContext.Controller as Controller;
      var httpContext = controller.HttpContext;

          Model\_Admin\_Login pResult = SecurityCookies.CookieRead\_Admin\_Login(httpContext);
          if (pResult.AccountName != null)
          {   
              Model\_Admin\_Login model = new Model\_Admin\_Login();
              bool result = EF\_Website\_Users.AdminCheck\_AccountName(pResult.AccountName, ref model);
              if (true == result)
              {
                  // Program the HttpContext.Current
                  // This will persist for the current cycle only
                  String\[\] newRoles = { "Administrator" };
                  GenericIdentity newIdentity = new GenericIdentity(pResult.AccountName);
                  GenericPrincipal newPrincipal = new GenericPrincipal(newIdentity, newRoles);
                  httpContext.User = newPrincipal;
                  System.Threading.Thread.CurrentPrincipal = httpContext.User;
      
                  // Store the Global ViewData to Show the Admin Menu or Not                    
                  controller.ViewData\["Admin\_Menu"\] = true;
                  controller.ViewData\["Admin\_UserID"\] = model.ID;
                  controller.ViewData\["Admin\_UserName"\] = pResult.AccountName.ToLower();
                  controller.ViewData\["Admin\_ImageUrl"\] = model.Avatar.Url;
                  controller.ViewData\["Admin\_ImageAlt"\] = model.Avatar.Alt;
                  controller.ViewData\["Admin\_Base64"\] = mode
      
      F 1 Reply Last reply
      0
      • J jkirkerx

        I'm no expert at this by far. But I'll mention the HttpContext. It has a lifespan of one cycle and is stateless. So I made a Attribute that you decorate the controller ActionResult with. It runs run before the ActionResult is fired, and passes everything downstream. Basically it's session free so you don't have to worry about restarts or what server you hit. I do remember this being a little buggy, in terms of having to erase the cookie a couple of times when exiting debug and starting again, but I think I fixed it.

        [AdminCheck]
        public IActionResult SomeEditor()

        The AdminCheck reads the cookie with special data in it, and if the user authenticates, it creates a new HttpContext.User using a GenericIdentity and GenericPrincipal I wrote this for .Net Core

        [AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
        public class AdminCheckAttribute : ActionFilterAttribute, IActionFilter
        {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
        var controller = filterContext.Controller as Controller;
        var httpContext = controller.HttpContext;

            Model\_Admin\_Login pResult = SecurityCookies.CookieRead\_Admin\_Login(httpContext);
            if (pResult.AccountName != null)
            {   
                Model\_Admin\_Login model = new Model\_Admin\_Login();
                bool result = EF\_Website\_Users.AdminCheck\_AccountName(pResult.AccountName, ref model);
                if (true == result)
                {
                    // Program the HttpContext.Current
                    // This will persist for the current cycle only
                    String\[\] newRoles = { "Administrator" };
                    GenericIdentity newIdentity = new GenericIdentity(pResult.AccountName);
                    GenericPrincipal newPrincipal = new GenericPrincipal(newIdentity, newRoles);
                    httpContext.User = newPrincipal;
                    System.Threading.Thread.CurrentPrincipal = httpContext.User;
        
                    // Store the Global ViewData to Show the Admin Menu or Not                    
                    controller.ViewData\["Admin\_Menu"\] = true;
                    controller.ViewData\["Admin\_UserID"\] = model.ID;
                    controller.ViewData\["Admin\_UserName"\] = pResult.AccountName.ToLower();
                    controller.ViewData\["Admin\_ImageUrl"\] = model.Avatar.Url;
                    controller.ViewData\["Admin\_ImageAlt"\] = model.Avatar.Alt;
                    controller.ViewData\["Admin\_Base64"\] = mode
        
        F Offline
        F Offline
        F Margueirat
        wrote on last edited by
        #3

        Thanks for your reply Jim. I will look into the example you provided. When you said "It has a lifespan of one cycle and is stateless.", you mean that it won't survive a IIS/Server reboot? As long as it keeps track of sessions (which I'm pretty sure it does), we are OK with it. Thanks you

        J 1 Reply Last reply
        0
        • F F Margueirat

          Thanks for your reply Jim. I will look into the example you provided. When you said "It has a lifespan of one cycle and is stateless.", you mean that it won't survive a IIS/Server reboot? As long as it keeps track of sessions (which I'm pretty sure it does), we are OK with it. Thanks you

          J Offline
          J Offline
          jkirkerx
          wrote on last edited by
          #4

          On the contrary quite the opposite. Because it reads the cookie you set with say the user name and a special token you craft when validated or authenticated the first time, the attribute will revalidate the authentication being stateless and durable, it will survive a server reboot, or say a worker process recycle and can be used in multiple Docker containers using Kubernetes. Just add another column to your user database table to store a token that you carefully craft. Using Sessions to store a value or to maintain authentication is dangerous and not durable in an environment that is suppose to be stateless. It may work today, but can be the cause of your worst mistake ever.

          If it ain't broke don't fix it Discover my world at jkirkerx.com

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups