locked
User Roles and Authentication. RRS feed

  • Question

  • User-1694438709 posted

    Currently spending my time at home building an Application in MVC ASP.Net Core for a college assignment. I've managed to get both a login and registration form working and I'm now looking at User Roles and Authentication. Just looking for some guidance on the best way of doing this.

    Currently I have a 'Roles' field entered into my DB with either 'Admin' and 'User', I then made an 'Admin' and 'Users' Controller linking them to different pages:

    [Authorize(Roles="Admin")]
        public class AdminController : Controller
        {
            private readonly DefaultContext _context;
            public AdminController(DefaultContext context)
            {
                _context = context;
            }
            public IActionResult Index()
            {
                return View();
            }
        }

    I'm not quite sure on how I go about checking the [Authorize(Roles="Admin")]  to the 'Roles' column within my database? 

    Friday, March 27, 2020 1:08 PM

Answers

  • User711641945 posted

    Hi binaary,

    Here is a working demo like below:

    1.Model:

    public class User
    {
        public int Id { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public int RoleId { get; set; }
        public Role Role { get; set; }
    }
    public class Role
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<User> Users { get; set; }
    }

    2.VIew:

    @model User
    
    <h4>User</h4>
    <hr />
    <div class="row">
        <div class="col-md-4">
            <form asp-action="Login" asp-route-returnUrl="@ViewData["ReturnUrl"]">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <div class="form-group">
                    <label asp-for="UserName" class="control-label"></label>
                    <input asp-for="UserName" class="form-control" />
                    <span asp-validation-for="UserName" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Password" class="control-label"></label>
                    <input asp-for="Password" class="form-control" />
                    <span asp-validation-for="Password" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <input type="submit" value="Create" class="btn btn-primary" />
                </div>
            </form>
        </div>
    </div>
    

    3.UsersController:

    public class UsersController : Controller
    {
        private readonly YourContext _context;
    
        public UsersController(YourContext context)
        {
            _context = context;
        }
        public IActionResult Login(string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            return View();
        }
    
        //[AllowAnonymous]
        [HttpPost]
        public async Task<IActionResult> Login(User userModel,string returnUrl = null)
        {
            if (ModelState.IsValid)
            {
                var user = _context.User.Include(u => u.Role)
                            .Where(u => u.UserName==userModel.UserName && u.Password == userModel.Password)
                            .FirstOrDefault();
                var claims = new List<Claim>
                {
                    new Claim(ClaimTypes.Name, user.UserName),
                    new Claim(ClaimTypes.Role, user.Role.Name)
                };
    
                ClaimsIdentity userIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
                ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity);
    
                var authProperties = new AuthenticationProperties
                {
                    IsPersistent = true,
                    ExpiresUtc = DateTime.UtcNow.AddMinutes(10)
                };
    
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,principal, authProperties);
    
                return LocalRedirect(returnUrl);
            }
            else
            {
                ModelState.AddModelError("Password", "Email and/or Password wrong");
    
                return View();
            }
        }
    }

    4.HomeController:

    [Authorize(Roles= "Admin")]
    public class HomeController : Controller
    {
        [AllowAnonymous]
        public IActionResult Index()
        {
            return View();
        }
        
        public IActionResult Privacy()
        {
            return View();
        }
    }

    5.Startup.cs:

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public IConfiguration Configuration { get; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            });
    
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(options =>
                {
                    options.LoginPath = "/Users/Login";
                    options.LogoutPath = "/Users/Logout";
                });
    
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    
            services.AddDbContext<AuthenticationContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("AuthenticationContext")));
        }
    
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
    
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
    
            app.UseAuthentication();
    
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }

    Result:

    Best Regards,

    Rena

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, March 31, 2020 8:54 AM

All replies

  • User475983607 posted

    Currently spending my time at home building an Application in MVC ASP.Net Core for a college assignment. I've managed to get both a login and registration form working and I'm now looking at User Roles and Authentication. Just looking for some guidance on the best way of doing this.

    Currently I have a 'Roles' field entered into my DB with either 'Admin' and 'User', I then made an 'Admin' and 'Users' Controller linking them to different pages:

    [Authorize(Roles="Admin")]
        public class AdminController : Controller
        {
            private readonly DefaultContext _context;
            public AdminController(DefaultContext context)
            {
                _context = context;
            }
            public IActionResult Index()
            {
                return View();
            }
        }

    I'm not quite sure on how I go about checking the [Authorize(Roles="Admin")]  to the 'Roles' column within my database? 

    Security works out-of-the-box.  Just create a new project using the Identity template.  

    https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-new

    https://docs.microsoft.com/en-us/aspnet/core/security/authentication/scaffold-identity?view=aspnetcore-3.1&tabs=visual-studio

    Friday, March 27, 2020 1:35 PM
  • User-1694438709 posted

    Hey! Thanks for the reply.

    Sadly due to it being for a college assignment, I'm not allowed to use this!

    Friday, March 27, 2020 1:59 PM
  • User711641945 posted

    Hi binaary,

    Here is a working demo like below:

    1.Model:

    public class User
    {
        public int Id { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public int RoleId { get; set; }
        public Role Role { get; set; }
    }
    public class Role
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public List<User> Users { get; set; }
    }

    2.VIew:

    @model User
    
    <h4>User</h4>
    <hr />
    <div class="row">
        <div class="col-md-4">
            <form asp-action="Login" asp-route-returnUrl="@ViewData["ReturnUrl"]">
                <div asp-validation-summary="ModelOnly" class="text-danger"></div>
                <div class="form-group">
                    <label asp-for="UserName" class="control-label"></label>
                    <input asp-for="UserName" class="form-control" />
                    <span asp-validation-for="UserName" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <label asp-for="Password" class="control-label"></label>
                    <input asp-for="Password" class="form-control" />
                    <span asp-validation-for="Password" class="text-danger"></span>
                </div>
                <div class="form-group">
                    <input type="submit" value="Create" class="btn btn-primary" />
                </div>
            </form>
        </div>
    </div>
    

    3.UsersController:

    public class UsersController : Controller
    {
        private readonly YourContext _context;
    
        public UsersController(YourContext context)
        {
            _context = context;
        }
        public IActionResult Login(string returnUrl = null)
        {
            ViewData["ReturnUrl"] = returnUrl;
            return View();
        }
    
        //[AllowAnonymous]
        [HttpPost]
        public async Task<IActionResult> Login(User userModel,string returnUrl = null)
        {
            if (ModelState.IsValid)
            {
                var user = _context.User.Include(u => u.Role)
                            .Where(u => u.UserName==userModel.UserName && u.Password == userModel.Password)
                            .FirstOrDefault();
                var claims = new List<Claim>
                {
                    new Claim(ClaimTypes.Name, user.UserName),
                    new Claim(ClaimTypes.Role, user.Role.Name)
                };
    
                ClaimsIdentity userIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
                ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity);
    
                var authProperties = new AuthenticationProperties
                {
                    IsPersistent = true,
                    ExpiresUtc = DateTime.UtcNow.AddMinutes(10)
                };
    
                await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,principal, authProperties);
    
                return LocalRedirect(returnUrl);
            }
            else
            {
                ModelState.AddModelError("Password", "Email and/or Password wrong");
    
                return View();
            }
        }
    }

    4.HomeController:

    [Authorize(Roles= "Admin")]
    public class HomeController : Controller
    {
        [AllowAnonymous]
        public IActionResult Index()
        {
            return View();
        }
        
        public IActionResult Privacy()
        {
            return View();
        }
    }

    5.Startup.cs:

    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
    
        public IConfiguration Configuration { get; }
    
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
            });
    
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(options =>
                {
                    options.LoginPath = "/Users/Login";
                    options.LogoutPath = "/Users/Logout";
                });
    
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
    
            services.AddDbContext<AuthenticationContext>(options =>
                    options.UseSqlServer(Configuration.GetConnectionString("AuthenticationContext")));
        }
    
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
    
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();
    
            app.UseAuthentication();
    
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }

    Result:

    Best Regards,

    Rena

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, March 31, 2020 8:54 AM