Custom Authorization With Asp.net MVC
The whole advantage with MVC over webforms is extensibility at every point. Extensibility, Extensibility, Extensibility.
Authorization is a very important and every web project has there own needs and requirements. Full customisation is paramount.
Here I will show you a simple way to customise your authorization.
In MVC attributes are used to protect a controller method, so we to get started all we need to do is inherit from the AuthorizeAttribute class.
public class CustomAuthorizeAttribute : AuthorizeAttribute { protected override bool AuthorizeCore(HttpContextBase httpContext) { string[] users = Users.Split(','); if (!httpContext.User.Identity.IsAuthenticated) return false; if (users.Length > 0 && !users.Contains(httpContext.User.Identity.Name, StringComparer.OrdinalIgnoreCase)) return false; return true; } } |
This is the basics. We can put any logic we like in here and all we have to do is return false if for whatever reason the user should not be authorized. Then all you need to do is decorate the controller method with the new attribute as below.
[CustomAuthorize] public ActionResult Index() { return View(); } |
From this simple example we can expand it with custom Roles.
public class CustomAuthorizeAttribute : AuthorizeAttribute { // the "new" must be used here because we are hiding // the Roles property on the underlying class public new SiteRoles Roles; protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext == null) throw new ArgumentNullException("httpContext"); string[] users = Users.Split(','); if (!httpContext.User.Identity.IsAuthenticated) return false; SiteRoles role = (SiteRoles)httpContext.Session["role"]; if (Roles != 0 && ((Roles & role) != role)) return false; return true; } } |
Where the SiteRoles class is defined as below.
[Serializable] [Flags] public enum SiteRoles { User = 1 << 0, Admin = 1 << 1, Helpdesk = 1 << 2 } |
This can then be used be used as follows.
[CustomAuthorize(Roles=SiteRoles.Admin|SiteRoles.HelpDesk)] public ActionResult Index() { return View(); } |
This will only allow the Admin and the Helpdesk Role access to the Index controller. If you don’t belong to one of these roles then you will be sent to the Login page.
The possibilities are really endless.
Happy coding.
Adam


[...] method, so we to get started all we need to do is inherit from the AuthorizeAttribute class.Click here to see the solutionHappy CodingAdam Posted: Feb 17 2009, 09:27 PM by schotime | with no comments Filed under: C#, [...]
Nice post – helped me to a better understanding of the AuthorizeAttribute.
What if I wanted a user who had already authenicated to be shown a “You are not authorized to view this page” when invoking the Index ControllerAction above, instead of being sent to the Login-page once again.
If I understand the code above correctly, a user with the SiteRoles.User role could be sent to the Login-page twice if he first invoked a controllerAction having the CustomAuthorize attribute set to allow users with the role SiteRoles.User, and then invoked a controllerAction like the Index controllerAction in the code above (only allowing SiteRoles.Admin or SiteRoles.HelpDesk)…
your thoughts?
Was looking for custom role in mvc. but if you use bit operator why not use
var role (SiteRoles)httpContext.Session["role"]);
return (Roles & role) == role;
you don’t need to split string or trim it.
@Achu
I’m new to the whole bitwise operators.
Gave that a try though and it works great.
Will update the article to reflect this.
Thanks.
@Rasmus M
I have had a look at this and you can do it.
If you put the [CustomAuthroize] attribute on the controller and [CustomAuthroize(Roles = SiteRoles.Admin)] on the action method then only admin people will be allowed through. If you try to access the page with a SiteRoles.User then you will be sent to the “NotAuth” view. This can easily be changed.
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
// the “new” must be used here because we are overriding the Roles property on the underlying class
public new SiteRoles Roles;
private bool FailedRolesAuth = false;
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null)
throw new ArgumentNullException(“httpContext”);
if (!httpContext.User.Identity.IsAuthenticated)
return false;
string[] users = Users.Split(‘,’);
if (!httpContext.User.Identity.IsAuthenticated)
return false;
if (users.Length > 0 && !users.Contains(StateManager.ContactName, StringComparer.OrdinalIgnoreCase))
return false;
SiteRoles role = (SiteRoles)httpContext.Session["role"];
if (Roles != 0 && (Roles & role) != role)
{
FailedRolesAuth = true;
return false;
}
return true;
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (FailedRolesAuth)
{
filterContext.Result = new ViewResult { ViewName = “NotAuth” };
}
}
}
This will redirect you to the “NotAuth” view if you fail the role logic.
Great post! I’ve been looking for how to implement custom authorization of MVC. Really like the idea of how you’re managing the SiteRoles and/or logic. Kinda confusing at first though.
Hi,
Nice Post.
Now i Understand how the AuthorisazinFlags work.
Im sittin here and mull over a Problem:
I want to use the Authorization Flag but in another Form
Ive got a Detail View example /Report/1
Now a User got more than one Rights
Example : User a Rights 1 -> 1024 , 2 -> 2048
the 1 stands for the view and the 1024 for a Bitmask. I want to mage it as dynamicle as possible.
But i dont know how … Any Ideas ?
Excellent tutorial. Now I’m a bit confused:
Where/When would you set:
httpContext.Session["role"]?
ThanX in advance.
I would set this on login usually.
Thanks
Excellent post.
In addition I was looking for giving filtered access to records based on user’s location. In other words, in my application, users are assigned different locations (branches). I want user from a branch should be able to access records entered by users of that branch only. I have UserLocation and Location table to manage assignment. Could you please guide me for this.
Thank you.
Nice post.thanks
And how would I need to assign my custom role to a user I add in the controller?
Thank you for sharing I wish I could go somwhere.
Great!
Thanks for this; a great tip. I just wanted to mention that you can also put this on the Controller class as a whole if you want to protect all actions of the controller with less code.
Thanks a lot.
I’ve implemented custom membership provider that requests re-login when session is finished (form authentication still keeps me on page when I don’t have credential for retrieving data.. ) Your article helps me solve it.!
This won’t work with caching, and will introduce a security flaw.
See p.334/335 of Pro ASP.Net MVC 2 Framework.
Thanks for post, helped in my digging.
Please change comment in code
// the “new” must be used here because we are overriding the Roles property on the underlying class
new doesn’t override, it hides parent property.
To override we use “override” keyword.
To create new member and hide parent’s member we use “new” keyword.
Hi,
Thanks! I have implemented this solution and adapt it to my membership model.
The problem is that
string[] users = Users.Split(‘,’);
always only contains “” ? Should it not have the name of the current user?
BestRegards
Does the Users array have any items in it?
Hey I dig your VS color scheme can you send me a copy of the settings? Also never seen the double << whats that?
[...] http://schotime.net/blog/index.php/2009/02/17/custom-authorization-with-aspnet-mvc/ [...]
My VS theme is based on this: http://blog.wekeroad.com/2007/10/17/textmate-theme-for-visual-studio-take-2/
The << is the shift operator.
The only issue I see with this code is that couldn’t you spoof what user group you belong to by simply changing your session role variable on the client side?
If that’s the case, then would obfuscating the role session variable get around the issue by removing the predictability of your role ids?
@Garry,
You cannot change the session variable from the client side.
It never gets sent to the client
@Schotime
Ah that’s right. I got my session storage and cookie storage mixed up
.
THANKS A LOT
This post helped me a lot..
[...] stumbled across this web post about making a custom Authorize attribute. Notice how they are checking the logged in users role [...]
WOW! Thank you so much for this article. This helped me SO much!