Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I seed users and roles in my asp.net core 3.1 application?

I tried using protected override void OnModelCreating(ModelBuilder builder) in my IdentityDataContext class and creating a migration that will seed this data:

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        // Customize the ASP.NET Identity model and override the defaults if needed.
        // For example, you can rename the ASP.NET Identity table names and more.
        // Add your customizations after calling base.OnModelCreating(builder);
        const string ADMIN_ID = "b4280b6a-0613-4cbd-a9e6-f1701e926e73";
        const string ROLE_ID = ADMIN_ID;
        builder.Entity<IdentityRole>().HasData(new IdentityRole
        {
            Id = ROLE_ID,
            Name = "admin",
            NormalizedName = "ADMIN"
        });
        builder.Entity<MyIdentityUser>().HasData(new MyIdentityUser
        {
            Id = ADMIN_ID,
            UserName = "[email protected]",
            NormalizedUserName = "[email protected]",
            Email = "[email protected]",
            NormalizedEmail = "[email protected]",
            EmailConfirmed = true,
            PasswordHash = "AQABBAEABCcQAABAEBhd37krE/TyMklt3SIf2Q3ITj/dunHYr7O5Z9UB0R1+dpDbcrHWuTBr8Uh5WR+JrQ==",
            SecurityStamp = "VVPCRDAS3MJWQD5CSW2GWPRADBXEZINA",
            ConcurrencyStamp = "c8554266-b401-4519-9aeb-a9283053fc58"
        });
        builder.Entity<IdentityUserRole<string>>().HasData(new IdentityUserRole<string>
        {
            RoleId = ROLE_ID,
            UserId = ADMIN_ID
        });
    }

which seems to work, but I cannot access my endpoint in Razor Page decorated with Authorize atribute. It's strange because I have all this data in my database. I can log in as this user and I see that there is "admin" role in AspNetRoles table. I have also user mapped to role correctly in AspNetUserRoles table.

[Authorize(Roles="admin")]
public class IndexModel : PageModel
{
    public async Task<IActionResult> OnGetAsync()
    {
        return Page();
    }

}

I'm being redirected to access denied page when logged as the user above which according to database has the admin role.

I saw that some people try to do this seed method in Configure method in Startup class, but I'm currently having trouble with dependency injection when i try to do this with RoleManager and UserManager:

System.InvalidOperationException: No service for type 'Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdentityRole]' has been registered.

like image 907
Tomasz Sikora Avatar asked Dec 07 '19 18:12

Tomasz Sikora


People also ask

What are seed users and roles in core identity?

Seed Users and Roles Data in ASP.NET Core Identity. ASP.NET Core identity allows you to implement authentication and authorization for your web applications. While working with ASP.NET Core Identity at times you need to create default user accounts and roles in the system.

What is ASP NET Core Identity?

Seed Users and Roles Data in ASP.NET Core Identity ASP.NET Core identity allows you to implement authentication and authorization for your web applications. While working with ASP.NET Core Identity at times you need to create default user accounts and roles in the system.

How to implement authentication and authorization in MVC with core identity?

With the help of ASP.NET Core identity, you can implement authentication and authorization for your web applications. Working with ASP.NET Core Identity, sometimes you have to create a default user accounts and roles in the system. In ASP.NET MVC it can be done in Global.asax and Application_Start event handler.

How do I use seeddata() and seedroles() methods?

The SeedData () method accepts a UserManager and a RoleManager. Inside, it calls SeedRoles () and SeedUsers (). Note that SeedRoles () is called first because SeedUsers () assigns certain roles to the users being added and those roles must exist in the system prior to adding the users. Finally, it's time to use the MyIdentityDataInitializer class.


1 Answers

I was almost there. It was not obvious at first, but I needed to add .AddRoles<IdentityRole>() line in my Configure method of IdentityHostingStartup.cs file.

It's mentioned at the end of Role-based authorization page from asp.net core 3.1 documentation: link to the documentation

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>()
        .AddRoles<IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddControllersWithViews();
    services.AddRazorPages();
}

I thought that roles are already taken into consideration and I don't need to explicitly add this functinality.

It should be stated on top of the page that in order to add role-based authorization you need to add .AddRoles<IdentityRole>() to your Configure method. Instead you are presented with many combinations of Authorization attribute and then at the bottom there is a brief paragraph "Add Role services to Identity" which gives no explanation that this is what makes it all to work.

like image 99
Tomasz Sikora Avatar answered Nov 01 '22 13:11

Tomasz Sikora