Search code examples
asp.net-mvc-4nhibernateforms-authentication

FormsAuthentication and database backed nested roles


I am reading into the FormsAuthentication for migrating a legacy application. This application uses the following structure for roles/permissions of users:

class Account
{
    public ISet<Role> Roles
    {
        get;
        set;
    }

    public static bool Has(Permission permission_)
    {
        foreach (Role role in Roles) {
            if (role.Permissions.Contains(permission_)) {
                return true;
            }
        }

        return false;
    }

}

class Role
{
    public ISet<Permission> Permissions
    {
        get;
        set;
    }
}

public enum Permission
{
    ACCESS_COMPONENT_XYZ
    EDIT_FIELD_ABC
    VIEW_ENTITY_123
}

Roles are just a collection of permissions, and in the code itself, only the permissions are checked, e.g.

model.CanEditFieldAbc = account.Has(Permission.EDIT_FIELD_ABC);

All of this is backed by the database using NHibernate. Now, as I understand FormsAuthentication, this uses a "one-dimensional" approach to Roles. Meaning, that I only have one field in the AuthenticationToken to fill in my permissions.

I believe that I need to somehow get all the permissions of the Account entity into the current authenticated token. My problem is: How do I do that? I understand how to authenticate, but not how to get my custom set of permissions (as strings e.g.) into that token?

Currently my login controller looks like this:

// "Accounts" is a NHibernate repository on the base controller
Account account = Accounts.Unique(form_.Name);

if (account != null) {
    byte[] salt = Convert.FromBase64String(account.Salt);
    byte[] password = Convert.FromBase64String(account.Password);

    if (PWDTK.ComparePasswordToHash(salt, form_.Password, password)) {
        FormsAuthentication.SetAuthCookie(form_.Name, false);
        // How to get the complete set of "account.Roles -> Permission" into the Cookie/Token?
    }
    else {
        throw new AuthenticateException("Wrong credentials");
    }
}
else  {
    throw new AuthenticateException("Wrong credentials");
}

Of course, I could just fetch the current account from the database for every request and then I'd have the set of roles/permissions inside of it (thanks to nhibernate lazy loading etc.), but that seems wrong given that the FormsAuthenticate already provides something similar to this?


Solution

  • Roles are supposed to be handled by a role provider. In your case you should write and configure your own role provider.

    On login, your code will not have to care about providing roles, the framework will use the role provider you have defined in configuration. You will only need to call RedirectFromLoginPage on successful login (or SetAuthCookie if you do not want to use the builtin redirect).

    And for checking roles, you should then use User IsInRole method.