Custom RoleProvider and Custom Principal

Last post 05-30-2008 5:55 AM by westcoastr13. 2 replies.

Sort Posts:

  • Custom RoleProvider and Custom Principal

    05-25-2008, 8:53 AM
    • Member
      186 point Member
    • french_duke
    • Member since 02-06-2007, 7:18 PM
    • Dundee, Scotland
    • Posts 127

    Hi folks

    I am implementing asp.net 2.0 roles and authentication for the first time so bear with me if my ideas are a bit mixed-up!

    I have written a CustomRoleProvider class which overrides all the necessary members required to use my custom datastore for user roles - and this appears to be working great. Next, I posted asking  how to store extra information for my user as I require access to a userId (representing the primary key from my users table), companyId and company name (similar database columns).

    I was advised to create a Custom Principal class (implementing the IPrincipal interface), and to add properties to this class to store the data I need, then on the Application_AuthenticateRequest event I initialise my CustomPrincipal object, sending in the data from the database. Here is the code:

    CustomPrincipal.cs

     

    public class CustomPrincipal : IPrincipal
    {
        #region "Private member variables"
    
        private IIdentity _identity;
        private int _userId;
        private int _companyId;
        private string _companyName;
    
        #endregion
    
        #region "Public member properties"
    
        public IIdentity Identity
        {
            get
            {
                return _identity;
            }
        }
    
        public int UserId
        {
            get
            {
                return _userId;
            }
            set
            {
                _userId = value;
            }
        }
    
        public int CompanyId
        {
            get
            {
                return _companyId;
            }
            set
            {
                _companyId = value;
            }
        }
    
        public string CompanyName
        {
            get
            {
                return _companyName;
            }
            set
            {
                _companyName = value;
            }
        }
    
        #endregion
    
        public CustomPrincipal(IIdentity identity, int userId, int companyId, string companyName)
        {
            _identity = identity;
            _userId = userId;
            _companyId = companyId;
            _companyName = companyName;
        }
    
        // IPrincipal Implementation
        public bool IsInRole(string role)
        {
            //How do I implement this?
            return true;
        }
    
    }
      

    Global.asax

     

    protected void Application_AuthenticateRequest(object sender, EventArgs e)
        {
            // Extract the forms authentication cookie
            string cookieName = FormsAuthentication.FormsCookieName;
            HttpCookie authCookie = Context.Request.Cookies[FormsAuthentication.FormsCookieName];
    
            if (authCookie == null)
                return;
    
            FormsAuthenticationTicket authTicket = null;
            try
            {
                authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            }
            catch
            {
                return;
            }
    
            if (authTicket == null)
                return;
            
            //Get extra user data from database
            UserClass u = new UserClass(); //BLL object
            int userId = 0;
            int companyId = 0;
            string companyName = string.Empty;
    
            FormsIdentity id = new FormsIdentity(authTicket);
    
            UserDataSet.UserDataTable users = u.GetUserByName(id.Name);
    
            if (users.Rows.Count > 0)
            {
                UserDataSet.UserRow user = (UserDataSet.UserRow)users.Rows[0];
                userId = user.UserID;
                
                if (!user.IsCompanyIDNull())
                {
                    companyId = user.CompanyID;
                    companyName = user.CompanyName;
                }
            }
            
            // This principal will flow throughout the request.
            CustomPrincipal principal = new CustomPrincipal(id, userId, companyId, companyName);
            // Attach the new principal object to the current HttpContext object
            Context.User = principal;
        }

     

    My questions are:

    1. How do I implement the IsInRole(string role) method of the CustomPrincipal? Have I now made my CustomRolePovider redundant?

    2. By getting the user data on every page load (which seems to be how often the Application_AuthenticateRequest event is fired) I am making an extra round-trip to the database. Is there a more efficient but equally secure way of persisting this data?

    3. Finally, should I really be creating a custom Principal to hold the extra properties, or should it really be a custom Identity?

    Sorry if this is a lengthy problem - I hope someone has the patience to read it!

    Thanks in advance!

    Duke
  • Re: Custom RoleProvider and Custom Principal

    05-28-2008, 4:24 PM
    Answer
    • Member
      186 point Member
    • french_duke
    • Member since 02-06-2007, 7:18 PM
    • Dundee, Scotland
    • Posts 127

    Hey folks

    I must have said something to offend everyone...!

    Just in case anyone has is checking this post out, I have gone down the route of serialzing my custom user class and storing the text stream into the UserData property of the FormsAuthenticationTicket - as demonstrated in this post. I then have a GetCurrentUser method which deserializes the UserData in the ticket, and returns me a custom user object with the one or two properties I needed to persist for each user.

    Hopefully this helps someone looking to do the same as me. Although it's too late for me to change this now - I still wouldn't mind if someone wanted to post a better solution.

     

    Duke
  • Re: Custom RoleProvider and Custom Principal

    05-30-2008, 5:55 AM
    • Member
      2 point Member
    • westcoastr13
    • Member since 05-30-2008, 5:47 AM
    • Dublin, Ireland
    • Posts 1
    Hey Duke,

     

    You have the right idea.  If you wanted, you could take it one step further and write a custom HttpModule to handle the authentication event which deserializes the principal for you from the encrypted cookie and manually assigns it to Context.User.  The only drawback is that you'll need to handle the cookie creation and authorization yourself.  You can see an example here

Page 1 of 1 (3 items)