Saturday, February 8, 2014

Using custom roles with ASP.Net Identity v2-alpha

When creating a new ASP.Net MVC 5 site we are given the option to choose the type of authentication we want for the site. If we choose "Individual accounts" the site is configured to use forms authentication with an Entity Framework backend. This backed uses ASP.Net Identity, which is the replacement for ASP.NEt Membership. In a test project I have, I decided I wanted to use the pre-release version of ASP.Net Identity, which, at the moment, is version 2-alpha. To upgrade to this version, we only have to upgrade the package from Nuget. We open the Nuget package manager and we select we want packages from the pre-release channel. Then we can update to the pre-release packages.

Once we have updated the project to use the pre-release version of ASP.NEt Identity we should enable Migrations for the Code first context we have on our app. To do so, we open the 'Package Manager Console' and we issue the command 'Enable-Migrations'. After we enable migrations we should create the initial migration: 'Add-Migration Initial'. This creates a migration file which can be used to update the database. We can then create the database table with 'Update-Database'.

When we have the initial migration applied we can add Properties to the ApplicationUser class:

public class ApplicationUser : IdentityUser
{
    public DateTime Birthday { get; set; }
}

After we add the property to the model, we have to create a Migration for it to be applied to the Database. We run the command 'Add-Migration AddBirthday'. This will create another migration file with the modifications it has to do to the database. We can apply this modifications with 'Update-Database'.

With the default classes we can only add fields to the Users class. If we want to add a property to the Roles we have to do some more work. First we create classes that inherit from 'IdentityRole', 'IdentityUserLogin', 'IdentityUserClaim' and 'IdentityUserRole':


public class ApplicationRole : IdentityRole
{
    public ApplicationRole()
    {
        Id = Guid.NewGuid().ToString();
    }

    public ApplicationRole(string roleName):this()
    {
        Name = roleName;
    }

    public bool Blocked { get; set; }
}

public class ApplicationUserLogin:IdentityUserLogin
{
}

public class ApplicationUserClaim:IdentityUserClaim
{
}

public class ApplicationUserRole:IdentityUserRole
{
}

And we update the 'ApplicationUser' class to reference our new classes:

public class ApplicationUser : IdentityUser
{
    public ApplicationUser()
    {
        Init();
    }

    private void Init()
    {
        Id = Guid.NewGuid().ToString();
    }
}

Then we have to change our 'ApplicationDbContext' class:

public class ApplicationDbContext : IdentityDbContext
{
    public ApplicationDbContext()
        : base("DefaultConnection")
    {
    }
}

With all this in place, we can create a new migration to use our new classes and add the 'Blocked' property to 'Roles'. Again, we use 'Add-Migration UpdatedRoles' and then 'Update-Database'. With this we have customized the Role class and the values we assign to this property are stored in the database.