heyNow
heyNow

Reputation: 886

MVC configurable Authorization filter

I want to make the [MyAuthorize(Role="R1")] attribute so that "R1" can be made configurable instead of hardcoding on Controller / Action.

The usual approach of creating a [MyAuthorize(Role="R1")] seems to be

public class MyAuthorizeAttribute : AuthorizeAttribute
{
    private readonly string[] _allowedRoles;

    public MyAuthorizeAttribute(params string[] roles)
    {
        this._allowedRoles = roles;
    }
    protected override bool OnAuthorization(AuthorizationContext 
                                             authorizationContext)

    {
        bool authorize = false;

        // Compare current user's Roles with "R1" to figure out if the 
        // Action / Controller can be executed   

        return authorize;
    }
}

But what if Roles like "R1" are subject to change at any time ? i.e., being "R1" one day and being called "AssistantManager" another day.

The application will have to be re-coded to handle this.

I thought of creating a custom [OnAuthorize] attribute that reads (Action/Controller, Role) as key value pairs from the web.config.

Eg:--

  <add key="Controller1" value="Role1" />
  <add key="Action2" value="Role2" />

and in the attribute..

protected override bool OnAuthorization(AuthorizationContext 
                                         authorizationContext)

{
    bool authorize = false;

    // 1. Read all key values 
    // 2. determine Action / Controller the user is trying to go
    // 3. Compare user's roles with those for Action / Controller

    return authorize;
}

I am aware of the limitations of <location .... /> in MVC as per https://stackoverflow.com/a/11765196/807246 and I'm not suggesting that, even though I'm reading from web.config

But what if we read (..and store in session??) all the authorization related configuration when the application first loads up?

Any changes like "R1" -> "AssistantManager" ;; "R2" -> "Manager" should just require a restart of the application, instead of having to make code changes in the controller / action.


I want to know if this is a valid approach or if there are security risks, even with this, and any better alternatives.

Upvotes: 0

Views: 786

Answers (1)

Wiktor Zychla
Wiktor Zychla

Reputation: 48314

Ad 1. You read the setting using the configuration API, e.g. if this is the regular MVC you have ConfigurationManager.AppSettings to peek into app settings section of the web.config

Ad 2. You don't determine anything or rather, you seem to misunderstood the linked post. What you do is you put the Authorize over the controller (action) you want to secure and the OnAuthorization is fired when the controller / action is executed. If you really want, you can peek into the authorization context passed as the argument, the controller and action are available in the route data.

Ad 3. This is the easiest part, the currently logged user (or an anonymous user if the user is not yet authenticated) is passed in the authorizationContext.HttpContext.User property as the IPrincipal so you can even call its IsInRole method.

But what if we read (..and store in session??) all the authorization related configuration when the application first loads up

You really don't have to. Even if you read it from the configuration upon every request, the configuration is already preloaded upon every restart of the application, you don't really slow anything down much then with ConfigurationManager.AppSettings.

Any changes like "R1" -> "AssistantManager" ;; "R2" -> "Manager" should just require a restart of the application, instead of having to make code changes in the controller / action.

If you store it in the configuration file and modifying it triggers the restart of the app pool, you don't make any changes in the code.

I want to know if this is a valid approach or if there are security risks, even with this, and any better alternatives.

There are risks, someone who can access your app server can possibly reconfigure your app. Note however, that such someone could do any other harm as well, e.g. decompile, modify, recompile and reupload your app. Or even replace it with something completely else.

As for alternatives, it's completely impossible to come up with anything better if the criteria of what's better are vague. If something is possibly better we'd have to know what better stands for.

In other, simple words, this looks fine.

Upvotes: 1

Related Questions