By default nothing will happen in your project when you install the NuGet package. In order for your authorization to happen you must apply the authorization rules using roles and/or policy.

Role based configuration

Here’s the simplest configuration:

<mvcAuthorization>
<areas>
<area>
<controllers>
<controller name="Home">
<actions>
<action name="Index">
</action>
</actions>
</controller>
<controller name="Account">
<actions>
<action name="LogOn">
</action>
</actions>
</controller>
</controllers>
</area>
</areas>
</mvcAuthorization>

This configuration will not lock anything down because there is no role/policy attribute applied to any of the nodes. If we wanted to lock down the home controller to users in the “ViewHome” role, we would apply the following attribute:

<controller name="Home" roles="ViewHome">

Note that the roles attribute can be applied at any level. For example, the following are also valid:

<area roles="GeneralAccess">
</area>


<action name="Index" roles="GeneralAccess">
</action>

Also notice that the <area> tag above does not have a name assigned to it. By default an area with no name is the root. There can only be one area with any given name, so if a second area were to be added it would need a unique name for itself.

Policy based configuration

So far everything we have seen has been locked down by role. What if we require a more robust way to lock down resources? This is where we would need a policy. A policy is simply a named piece of code that checks something to see if access should be granted to a resource. MvcAuthorization comes with the most common policies by default, which include:

  • DenyAnonymousAccess
  • DenyNoRoleAccess
  • LocalOnly
  • SecureConnectionOnly

For example, if we had an “Admin” area and wanted to ensure that the only way to get in was to be browsing locally on the machine hosting the website, we would have a configuration like below.

<area name="Admin">
<policies>
<policy name="LocalOnly" />
</policies>
<controllers>
<controller name="ManageUsers">
</controller>
</controllers>
</area>

Not unlike roles a policy can be applied at any level. If we wanted to lock down everything so that the user needed to be authenticated to see something, we would apply the policy at the root:

<mvcAuthorization>
<policies>
<policy name="DenyAnonymousAccess" />
</policies>
<areas>
   ...

However, you may notice that this presents a problem. What about the Logon action in the account controller? We do want to allow access to this resource as an exception. Luckily we can do just that by applying the configuration below:

<controller name="Account">
<actions>
<action name="LogOn">
<policies>
<policy ignoreInherited="true" name="DenyAnonymousAccess" />
</policies>
</action>
</actions>
</controller>

The ignoreInherited attribute will signal that the LogOn action should not honor the DenyAnonymousAccess policy.

Custom Policies

If the built in policies are not enough, a custom one can be added easily. Simply inherit from the AuthorizationPolicy base class, implement the ApplyPolicy method, and apply the PolicyMetadataAttribute to the policy.

For example, to allow/disallow access randomly to the About controller the following policy could be implemented:

[PolicyMetadata(Name = "RandomAccess")]
public class RandomAccessPolicy : AuthorizationPolicy
{
public ApplyPolicyResult ApplyPolicy(ApplyPolicyArgs args)
{
bool isAuthorized = RandomNumberGen.Generate(0, 1) == 1;
return new ApplyPolicyResult() { IsAuthorized = isAuthorized };
}
}
<controller name="About">
<policies>
<policy name="RandomAccess" />
</policies>
<actions>
...
</actions>
</controller>

Note that the PolicyMetadataAttribute is required, and the Name must be unique.

View Rendering

If a resource is locked down it is probably a good idea to not present links to users for which they do not have access. This can be achieved through the SecureActionLink Html helper:

@Html.SecureActionLink("Admin Link", "Index", "TopSecret", "Admin")

The helper has the link text and Action as required parameters, and the Controller/Area as optional parameters. It will query the configuration and only present links if the users permission levels are appropriate.

IoC container

By default MvcAuthorization will manage instantiation of depencencies (such as a policy class) internally. When this happens instances of the dependency will be static, and will require a default constructor. However you can override this behavior by telling MvcAuthorization how to resolve dependencies. If you are already using DependencyResolver you can achieve this by adding the code below to your Global.asax.cs file.

AuthorizationProvider.ResolveDependenciesUsing(type => DependencyResolver.Current.GetService(type));

Otherwise just replace the DependencyResolver part with your favorite IoC container. It is also worth noting that if this delegate responds to a request for an IAuthorizationProvider that provider will be used instead of the default Configuration provider. This is useful for implementing custom providers that get their data from a source other than Web.config. If the resolver responds to this interface request it is preferable to make the lifetime of of the instance is static so that caching can be effective.

Last edited Jul 13, 2013 at 3:16 PM by RyanMWright, version 1

Comments

Corix010 Jan 13, 2015 at 2:56 PM 
How to use SecureActionLink Html helper with parameters? The following line of code renders link without id:
@Html.SecureActionLink("Edit", "Edit", new { id = item.Id })