0

I have a method that returns a bool, true being the user is allowed to access the site and false being the user has not access to the site. As of right now I have a separate action that is called in each Action and if the user if the method returns false the user is directed to a view that says "access denied". I was wondering there is a better way to do this without throwing the duplicate code in each individual action any maybe replace it with one single call because the user will either be able to access all of the pages or non of the page.

Here is an example of what I have:

    [HttpGet]
    public ActionResult EmployeeAdd()
    {
        if (!GetUsersecurityLevel())
        {
            return RedirectToAction("NotAuthorizedForApplication");
        }

        ...........

        return View();
    }

    [HttpGet]
    public ActionResult EmployeeEdit()
    {
        if (!GetUsersecurityLevel())
        {
            return RedirectToAction("NotAuthorizedForApplication");
        }

        ..........

        return View();
    }

    [HttpGet]
    public ActionResult EmployeeDelete()
    {
        if (!GetUsersecurityLevel())
        {
            return RedirectToAction("NotAuthorizedForApplication");
        }

        ..........

        return View();
    }


    public string CurrentUserName()
    {
        return User.Identity.Name.Substring(User.Identity.Name.IndexOf(@"\", StringComparison.Ordinal) + 1).ToUpper();
    }

Web.Config:

  <system.web>
    <authentication mode="Windows" />
    <authorization><deny users="?"/></authorization>
    <compilation debug="true" targetFramework="4.0"/>
    <httpRuntime targetFramework="4.0"/>
    <customErrors mode="Off" />
  </system.web>

So my questions is: Can I make one single call on the GetUserSecurityLevel() which can protect all of the actions from being ran by unauthorized users?

user3788671
  • 1,977
  • 5
  • 29
  • 43
  • Have tried to create attribute that inherits from Authorize attribute and use it on the controller – Dan Hunex Oct 01 '14 at 22:18
  • Check my answer to this question: http://stackoverflow.com/questions/17455466/hybrid-of-windows-authentication-and-forms-authentication-in-asp-net-mvc-4 – ataravati Oct 01 '14 at 22:18

3 Answers3

3

Create a custom authorize attribute like this:

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var username = httpContext.User.Identity.Name;
        return GetUserSecurityLevel(username);
    }

    public override void OnAuthorization(AuthorizationContext filterContext)
    {            
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        if (!AuthorizeCore(filterContext.HttpContext))
        {
             // If not authorized, redirect to the NotAuthorizedForApplication action 
             filterContext.Result = new RedirectToRouteResult(
                new System.Web.Routing.RouteValueDictionary {
                   {"action", "NotAuthorizedForApplication"}
                }
             );               
        }
    }

    private bool GetUserSecurityLevel(string username)
    {
        // Your code to authorize users...
    }
}

Then, you can use it in your controller or actions like this:

[HttpGet]
[MyAuthorize]
public ActionResult EmployeeAdd()
{
    ...........

    return View();
}

However, if there's only one level of access, why don't you use NT groups (roles) for authorization?

UPDATE:

Make sure Windows Authentication is enabled on IIS, and in your web.config file, inside <system.web> you have:

<authentication mode="Windows" />
<authorization>
  <deny users="?" />
</authorization>
ataravati
  • 8,891
  • 9
  • 57
  • 89
  • I have to be able to get the username because this is using windows authentication. Is there anyway to add my CurrentUserName() method to the class? I – user3788671 Oct 01 '14 at 22:41
  • See my updated answer. You can get the current user from httpContext, and pass it to your method as a parameter. – ataravati Oct 01 '14 at 22:43
  • By the way, as I said, if the only thing you need to check is whether the users are authorized to access the application or not, you can add them all to an NT Role, and authorize that Role only either in your web.config file or in IIS. – ataravati Oct 01 '14 at 22:46
  • Okay, I will look into that as well. This line keeps returning an empty string. httpContext.User.Identity.Name; – user3788671 Oct 01 '14 at 22:50
  • That's probably because you haven't enabled Windows Authentication on IIS or in your web.config file. What do you have in your web.config file. Do you have this line in your web.config file: ``? – ataravati Oct 01 '14 at 22:57
  • It gets it when I call it in the controller though. And Windows Authentication is enabled on IIS. Yes, I have that line. – user3788671 Oct 01 '14 at 22:59
  • What do you have in your web.config file under ``? Also, make sure Anonymous is disabled on IIS. – ataravati Oct 01 '14 at 23:03
  • I added the piece of my web config. And i just checked IIS and it disabled. – user3788671 Oct 01 '14 at 23:08
  • Is that empty when you deploy to the server, or even when you run it on your local machine? – ataravati Oct 01 '14 at 23:40
  • its empty on both. Doesn't that mean it has to be the web config? – user3788671 Oct 01 '14 at 23:45
  • Give more details. How can I help you when all I know is you get a 401.2 error message? – ataravati Oct 03 '14 at 01:51
1

The following might help you. Once you override the AuthorizeCore , then you can use it in your controller and it will apply to all of your actions. You can also apply it to each action method independently

 public class AdminAuthorizeAttribute: AuthorizeAttribute
     {

      protected override bool AuthorizeCore(System.Web.HttpContextBase httpContext)
          {
              return !base.AuthorizeCore(httpContext)? false:GetUsersecurityLevel();
          }
     }

then on the controller

you can do

at Controller level

 [AdminAuthorize]
 public class YourController:Controller 
       {

       }

Or action level

 [HttpGet]
 [AdminAuthorize]
 public ActionResult EmployeeAdd()
Dan Hunex
  • 5,172
  • 2
  • 27
  • 38
0

Custom authorisation filter is the best solution as suggested by ataravati.

iaq
  • 173
  • 1
  • 2
  • 10