Reputation: 1132
I am new to .NET, MVC & Identity Framework. I noticed the identity framework allows for securing individual controller actions via annotations.
[Authorize]
public ActionResult Edit(int? Id){
//edit action
}
I would like to secure certain actions based on user permissions.
Example : A blog application where only the user who created a blog post can edit.
With this in mind, is it possible to perform either option below? If so, are there resources and examples on how to best achieve?
[Authorize(Entity = "Entry", Permission = "Edit", Id = Id)]
public ActionResult Edit(int? Id){
//edit action
}
or
[BlogEntryPermission(Permission = "Edit", Id = Id)]
public ActionResult Edit(int? Id){
//edit action
}
Where blog Id
is captured from the request.
Any information or direction on permission based authentication would be most appreciated. Thanks in advance for your help.
Upvotes: 9
Views: 11929
Reputation: 141
I hope your problem solved till now. But worth it to add a new solution. I've implemented a Permission-based extension for Microsoft Identity 2 membership system. It's an open source project and you can access to the repository here:
https://github.com/Arminkhodaei/Identity-Permission-Extension
Usage:
First approach:
// GET: /Manage/Index
[AuthorizePermission(Name = "Show_Management", Description = "Show the Management Page.")]
public async Task<ActionResult> Index(ManageMessageId? message)
{
//...
}
Second approach:
// GET: /Manage/Users
public async Task<ActionResult> Users()
{
if (await HttpContext.AuthorizePermission(name: "AllUsers_Management", description: "Edit all of the users information."))
{
return View(db.GetAllUsers());
}
else if (await HttpContext.AuthorizePermission(name: "UnConfirmedUsers_Management", description: "Edit unconfirmed users information."))
{
return View(db.GetUnConfirmedUsers());
}
else
{
return View(new List<User>());
}
}
Upvotes: 1
Reputation: 12324
You can implement your custom AuthorizationAttribute
where you will specify your parameters and can get a blogId
from request
public class AuthorizeEntryPermission : AuthorizeAttribute
{
public string Permission { get; set; }
public AuthorizeEntryPermission(){
}
public AuthorizeEntryPermission(string Permission)
{
this.Permission = Permission;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var id = context.Request.RequestContext.RouteData.Values["Id"];
//check your permissions
}
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (AuthorizeCore(filterContext.HttpContext))
{
// ** IMPORTANT **
// Since we're performing authorization at the action level, the authorization code runs
// after the output caching module. In the worst case this could allow an authorized user
// to cause the page to be cached, then an unauthorized user would later be served the
// cached page. We work around this by telling proxies not to cache the sensitive page,
// then we hook our custom authorization code into the caching mechanism so that we have
// the final say on whether a page should be served from the cache.
HttpCachePolicyBase cachePolicy = filterContext.HttpContext.Response.Cache;
cachePolicy.SetProxyMaxAge(new TimeSpan(0));
cachePolicy.AddValidationCallback(CacheValidateHandler, null /* data */);
}
else
{
//handle no permission
}
}
private void CacheValidateHandler(HttpContext context, object data, ref HttpValidationStatus validationStatus)
{
validationStatus = OnCacheAuthorization(new HttpContextWrapper(context));
}
}
Then use it like this:
[AuthorizeEntryPermission(Permission = "Edit")]
public ActionResult Edit(int? Id){
//edit action
}
Upvotes: 6
Reputation: 56859
MVC has roles built-in. You can make the roles as granular as you need - essentially making them like permissions. For example, you could make role names like:
Then you can set the roles up on your controller using the built-in AuthorizeAttribute.
[Authorize(Roles = "AddBlogPost")]
public ActionResult Add(){
//add action
}
[Authorize(Roles = "AddBlogPost")]
[HttpPost]
public ActionResult Add(BlogModel model){
//add action
}
[Authorize(Roles = "EditBlogPost")]
public ActionResult Edit(int? Id){
//edit action
}
[Authorize(Roles = "EditBlogPost")]
[HttpPost]
public ActionResult Edit(BlogModel model){
//edit action
}
[Authorize(Roles = "ViewBlogPost")]
public ActionResult View(){
//view action
}
Then it is just a matter of assigning the different roles to each user in your database.
Upvotes: 1