7

I would like to implement a role-based authorization in my web application that I'm building. The way I imagined to make this is to create 3 tables in my DB like following:

1. Roles
2. UserRoles (many to many table)
3. Users 

After that each user would have a role assigned to him. Now... My question is, How do I permit or forbid access to specific views/controllers inside my .NET MVC application. I've stumbled upon this:

[Authorize(Roles = "HrAdmin, CanEnterPayroll")]
[HttpPost]
public ActionResult EnterPayroll(string id)
{
    //  . . . Enter some payroll . . . 
}

The Authorize property seems to be limiting the specific controllers/actions to specific roles... But what if I read the user roles from the table UserRoles like in my case?? How is my application gonna know what role does the User have on the system ??

Can someone help me out with this ?

User987
  • 3,663
  • 15
  • 54
  • 115

3 Answers3

7

Lets pretend you have stored your UserName and Roles in Session:

[AllowAnonymous]
[HttpGet]
public ActionResult Login()
{
    . . . .

    string userName = (string)Session["UserName"];
    string[] userRoles = (string[])Session["UserRoles"];

    ClaimsIdentity identity = new ClaimsIdentity(DefaultAuthenticationTypes.ApplicationCookie);

    identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, userName));

    userRoles.ToList().ForEach((role) => identity.AddClaim(new Claim(ClaimTypes.Role, role)));

    identity.AddClaim(new Claim(ClaimTypes.Name, userName));

    AuthenticationManager.SignIn(identity);

    . . . .
}
SᴇM
  • 7,024
  • 3
  • 24
  • 41
  • I've tried this method now, but it says that AuthenticationManager class doesn't contains SignIn method for some reason :/ – User987 Oct 28 '16 at 13:35
  • Add `using Microsoft.Owin.Security` reference – SᴇM Oct 28 '16 at 13:37
  • 1
    Here is [MSDN page](https://msdn.microsoft.com/en-us/library/microsoft.owin.security.iauthenticationmanager(v=vs.113).aspx) about `AuthenticationManager` class – SᴇM Oct 28 '16 at 13:40
  • Do you have `Microsoft.Owin`, `Microsoft.Owin.Security`, `Microsoft.Owin.OAuth` in your references? – SᴇM Oct 28 '16 at 13:42
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/126911/discussion-between-user987-and-sem). – User987 Oct 28 '16 at 13:43
  • private IAuthenticationManager AuthenticationManager { get { return HttpContext.GetOwinContext().Authentication; } } Add this method – yogeswaran K Feb 11 '20 at 17:02
1

if you Authorize a role to access a controller ( at class level ) or a action ( function level ) they roles will have access. otherwise the access is denied.

if you use just the Authorize keyword without specifying the roles or users, all authenticated users will have access.

hope fully i am making it clear ?

to use claims based identity refer to the following

https://msdn.microsoft.com/en-gb/library/ee517291.aspx

https://msdn.microsoft.com/en-gb/library/ff359101.aspx

this is on Core

What is the claims in ASP .NET Identity

Community
  • 1
  • 1
Emil
  • 281
  • 1
  • 2
  • 11
  • Yep I understand you. The issue here is, how do I add the roles from my DB so that the application knows which role the user has from the DB. @SeM said I could do it with something called "Claims" ... Is that the right way? – User987 Oct 27 '16 at 10:03
  • yes claims based is a way to go , i have modified my repose with some links which can help you – Emil Oct 27 '16 at 10:08
0

Here is some pieces of code how you can achieve that using Azure Active Directory. Configuring the application in Startup.cs:

public void ConfigureApplication(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    ...

    app.UseIISPlatformHandler();
    app.UseStaticFiles();

    app.UseCookieAuthentication(options =>
    {
        options.AutomaticAuthenticate = true;
    });            

    app.UseOpenIdConnectAuthentication(options =>
    {
        options.AutomaticChallenge = true;
        options.ClientId = Configuration.Get<string>("Authentication:AzureAd:ClientId");
        options.Authority = Configuration.Get<string>("Authentication:AzureAd:AADInstance") + "Common";
        options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;

        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = false,
            RoleClaimType = "roles"
        };
        options.Events = new OpenIdConnectEvents
        {
            OnAuthenticationValidated = (context) => Task.FromResult(0),
            OnAuthenticationFailed = (context) =>
            {
               context.Response.Redirect("/Home/Error");
               context.HandleResponse(); // Suppress the exception
               return Task.FromResult(0);
            },
            OnRemoteError = (context) => Task.FromResult(0)
        };
    });

    app.UseMvc(routes =>
    {
       routes.MapRoute(name: "default", template: "{controller=Dashboard}/{action=Index}/{id?}");                
    });

    DatabaseInitializer.InitializaDatabaseAsync(app.ApplicationServices).Wait();
}

And here is the usage:

[Authorize(Roles = "SuperAdmin, Worker")]
public ActionResult Index()
{
    ViewBag.Message = "Hello";
    return View();
}

and:

public ActionResult Submit(FormCollection formCollection)
{
    if (User.IsInRole("SuperAdmin") || User.IsInRole("Worker"))
    {
        ...
    }

    if (User.IsInRole("Admin"))
    { 
        //do some admin tasks
    }

    return RedirectToAction("Index", "Tasks");
}

Here is my blog post on that: http://www.eidias.com/blog/2016/1/16/using-azure-active-directory-application-roles. You can find there how to configure above roles in AAD.

Dawid Rutkowski
  • 2,658
  • 1
  • 29
  • 36