5

I'm building a web app that is essentially a store, but I want to put in an easy way for the admin of the site to add new products. However I want to restrict this part of the site so only the admin can access it. I have no use for other users at this moment.

How do I make it so that anybody with the admin username and password can access these pages and it will persist to know that they are logged in? I already have a system in place that accepts a user input and then continues to the admin pages if it's correct. But the problem is if someone decides to just go directly to the pages like Admin/AddProduct. I'd need my app to know that they're not allowed to access the AddProduct page yet and redirect them back to the login.

Joe Higley
  • 1,762
  • 3
  • 20
  • 33
  • You need to add some sort of permission system to your login. For asp.net you can use the [asp.net identity framework](https://learn.microsoft.com/en-us/aspnet/core/security/authentication/identity). – Mats391 May 02 '17 at 06:39
  • Right, I've looked into that, but I can't understand how I'd add my single admin user to whatever database it's pulling from. I don't want to have a register users link at all – Joe Higley May 02 '17 at 06:42
  • On startup you can check if your admin user exists and if it doesnt create it. You just need to call the same methods that are used in the register example with the values you want for you admin. – Mats391 May 02 '17 at 06:45
  • Does that only create one instance of it ever. This is a web app so my concern is that Everytime someone visits the site it doesn't call the startup and make a bunch of the same admin users – Joe Higley May 02 '17 at 06:55
  • You can check if the user exists before creating it. – Mats391 May 02 '17 at 06:59

2 Answers2

20

Here's how you go about it Joey

You could do this easily by creating a CreateRoles method in your startup class. This helps check if the roles are created, and creates the roles if they aren't; on application startup. Like so.

private async Task CreateRoles(IServiceProvider serviceProvider)
    {
        //initializing custom roles 
        var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
        var UserManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
        string[] roleNames = { "Admin", "Store-Manager", "Member" };
        IdentityResult roleResult;

        foreach (var roleName in roleNames)
        {
            var roleExist = await RoleManager.RoleExistsAsync(roleName);
            // ensure that the role does not exist
            if (!roleExist)
            {
                //create the roles and seed them to the database: 
                roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
            }
        }

        // find the user with the admin email 
        var _user = await UserManager.FindByEmailAsync("admin@email.com");

       // check if the user exists
       if(_user == null)
       {
            //Here you could create the super admin who will maintain the web app
            var poweruser = new ApplicationUser
            {
                UserName = "Admin",
                Email = "admin@email.com",
            };
            string adminPassword = "p@$$w0rd";

            var createPowerUser = await UserManager.CreateAsync(poweruser, adminPassword);
            if (createPowerUser.Succeeded)
            {
                //here we tie the new user to the role
                await UserManager.AddToRoleAsync(poweruser, "Admin");

            }
       }
    }

and then you could call the await CreateRoles(serviceProvider); method from the Configure method in the Startup class. ensure you have IServiceProvider as a parameter in the Configure class.

Question 2: "How do I make it so that anybody with the admin username and password can access these pages "

You can do this easily, like so.

[Authorize(Roles="Admin")]
public class ManageController : Controller
{
   //....
   Return View();
}

You can also use role-based authorization in the action method like so. Assign multiple roles, if you will

[Authorize(Roles="Admin")]
public IActionResult Index()
{
/*
 .....
 */ 
}

While this works fine, for a much better practice, you might want to read about using policy based role checks. You can find it on the ASP.NET core documentation here, or this article I wrote about it here

Temi Lajumoke
  • 2,350
  • 1
  • 14
  • 14
  • This works great and I will definitely mark it as the answer but I have one problem. For some reason it won't accept my login if the UserName and Email are not the same value. example: {UserName = "Joe@gmail.com", Email = "Joe@gmail.com"} works but {UserName = "Admin", Email = "Joe@gmail.com"} returns an invalid login when trying to login using the email and password. – Joe Higley May 03 '17 at 18:25
  • I figured it out. Apparently whoever created the default AccountController Login action didn't notice that SignInPasswordAsync uses the Username and Password and not the Email and Password. I had to change that and change the LoginViewModel by removing the dependency attribute 'EmailAddres' – Joe Higley May 04 '17 at 06:12
  • 1
    "ensure you have IServiceProvider as a parameter in the Configure class" --- can you give example how to do it? 1. in default asp.net core startup, there's no `Configure` class; 2. default injected is `IServiceCollection services` – Lei Yang Jun 15 '21 at 14:37
5

Once you add ASP.NET Identity to your project you can implement Role based Authorization in your application. Basically it allows you to setup [Authorize(Roles = "Administrator")] attribute for contollers which shall be available for admin users only.

Alexey Andrushkevich
  • 5,992
  • 2
  • 34
  • 49
  • 2
    Using roles is kinda discouraged and outdated concept. You should rather use the policy based authorization, where "role" is treated like a claim instead, since it's way more flexible then roles – Tseng May 02 '17 at 11:05
  • 1
    Agreed, but for a simple scenario described in the question the role based authorization might be more straightforward. In future it can be easily migrated to policy based authorization – Alexey Andrushkevich May 02 '17 at 11:35
  • How do I add identity to my project? – Joe Higley May 02 '17 at 16:23
  • Take a look [here](http://stackoverflow.com/questions/43714662/how-to-add-asp-net-identity-in-asp-net-core-with-visual-studio-code) – Alexey Andrushkevich May 02 '17 at 17:50