restrict user access to controller based on property in object (asp.net mvc) - asp.net

What is the best way to control user access to a controller. I have local User object with a property(boolean - "IsSubscribed"). Users can only access the controller if the value is true.
Notes:
I use forms authentication, but NO .net membership/profile etc.
mvc version 2

You could write a custom Authroize attribute:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var isAuthorized = base.AuthorizeCore(httpContext);
if (isAuthorized)
{
// Perform your custom authorization and return true/false
}
return isAuthorized;
}
}
and then decorate your controller/actions with this attribute.

Related

how implement exiting authentication roles in the database into AspNet IdentityRole

i've asp mvc application , database first , i have a table to hold my roles another for my users and junction table user_role.
i added the following class to my app
Microsoft.AspNet.Identity.Owin
Microsoft.AspNet.Identity.EntityFramework
Microsoft.Owin.Host.SystemWeb
can i use my existing tables to apply the roles to my controllers
[Authorize(Roles = "Admin")]]
public ActionResult MySecretAction() {}
or maybe
[Authorize(Roles = MyDBEntities.Roles.Find(1)]]
public ActionResult MySecretAction() {}
thank you
Can I use existing roles from db table?
Yes you can use existing roles from database.
You can use [Authorize(Roles = "Admin")], but not [Authorize(Roles = MyDBEntities.Roles.Find(1)] as it is not constant value, but dynamic.
But how can I add and remove roles to my existing tables when I assign a role to a user?
To add new role(s) you have to use RoleManager class with CreateAsync method along with other methods for managing roles used by your app.
When i add a role to a method , and the user is not authorized to use it , the application redirects him back to the login page ,where to change this?
To alter behavior during athorization you have to implement own Authorization attribute inherited from AuthorizeAttribute and override OnAuthorization method.
public class AuthorizeRoleAttribute : AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
// User is not authenticated(NOT logged in)
// we are letting ASP.NET to use standard procedure => redirect her/him to login page
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
base.HandleUnauthorizedRequest(filterContext);
}
// User is authenticated(logged in)
// we are going to show her/him custom view with error
else
{
// Don't forget to create Unauthorized.cshtml view in Shared folder
filterContext.Result = new ViewResult
{
ViewName = "~/Views/Shared/Unauthorized.cshtml"
};
}
}
}
Then you have to use your custom AuthorizeRoleAttribute instead the default one.
[AuthorizeRole(Roles = "Admin")]]
public ActionResult MySecretAction() {}
Resources:
RoleManager class
Implementing RoleManager in ASP.NET MVC 5
ASP.NET MVC 5 Identity: Extending and Modifying Roles
I've created a costume authorization class , witch i can user to access the logged in user and my databases tables
using System;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using System.Linq;
using System.Collections.Generic;
using LoanApp.Models.DataBaseModel;
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class DynamicAuthorize : AuthorizeAttribute
{
// public string DefaultURL { get; set; }
protected override bool AuthorizeCore(HttpContextBase context)
{ return true;
}
}

How to add logging for unauthorized access for [Authorize] filter in webapi

I created an ASP.NET Web API 2 end point, with controllers protected with the [Authorized] attribute.
Unauthenticated access will get 401 UnAuthorized http status.
Now, I want to log those unauthorized access to a log file. However, I don't know where to handle the unauthorized access.
The solution would just be to create a custom Authorize filter inheriting from default Authorize attribute this way:
public class LogAuthorizeAttribute : AuthorizeAttribute
{
protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
{
var authorized = base.IsAuthorized(actionContext);
if (!authorized)
{
// log the denied access attempt.
}
return authorized;
}
}
This way, you keep the same authorize validation from parent, but you can do additional thing such as logging in your case for unauthorized access.
You can then simply use it on your Web API methods:
public class ValuesController : ApiController
{
[LogAuthorize]
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
}

Accessing AuthorizationAttribute within Controller

I have a custom AuthorizeAttribute written in MVC. I have it applied to a controller for security. In that AuthorizeAttribute class I have written are several variables I gathered from a web service call I would like to access inside the controller to prevent having to call the web service again. Is this possible?
Your best approach would be to use HttpContext.Current.Items for storing those variables because that data will only be valid for a single http request. Something like this:
public class CustomAuthorize : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext.User.Identity == null) return false;
if (!httpContext.Request.IsAuthenticated) return false;
var user = new WSUser(); //get this from your webservice
if(user == null) return false;
httpContext.Items.Add("prop", user.Property);
return user.Authorized;
}
}
public class HomeController : Controller
{
[CustomAuthorize]
public ActionResult Index()
{
var property = (string) HttpContext.Items["prop"];
return View();
}
}
You would also want to encapsulate logic for storing and retrieving items from HttpContext.Current into a separate class to keep the code clean and to follow Single responsibility principle
You could save these variables in a static class to store it. But, a elegant solution would be to have a modelbinder object that you call like parameter in your controller and that read the static class and return the properties that you need.
Perhaps, if you are applying security, the best will be that call the webservices each once.
Reference for your custom model binder

getting Roles that already set to custom Authorization attribute?

I customized the authorize attribute of Asp.Net but I do not know how to get the roles which I set to the attribute when I set the attribute to a method or class
For example I have this CustomeAuthorizeAttribute
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomeAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (HttpContext.Current.User.Identity.IsAuthenticated && HttpContext.Current.User.IsInRole("Super"))
{
return true;
}
else
return false;
}
}
but I do not know how to get the roles when I set them to the attribute like this
[CustomeAuthorizeAttribute(Roles="admin,super-admin")]
by default it inhirits the Roles property from the base Authorize class so you can get the roles directly by using the Roles property
For Example
if (HttpContext.Current.User.Identity.IsAuthenticated && HttpContext.Current.User.IsInRole(Roles))
{
return true;
}
or you create new properties belong to your custom Authorization attribute and use them.

Securing ajax calls in a ASP.NET MVC application

I have an ASP.NET MVC based application that allows different levels of access depending on the user. The way it currently works is when a user accesses a page, a check is done against the database to determine the rights that user has. The view is then selected based on the level of access that user has. Some users see more data and have more functionality available to them than do others. Each page also makes a variety of ajax calls to display and update the data displayed on the page.
My question is what is the best way to ensure that a particular ajax call originated from the view and was not crafted manually to return or update data the user does not have access to? I would prefer not to have to go to the database to re-check every time an ajax call is made since that was already done when the user initially loaded the page.
Check out the Authorize Attribute, you can put it on an entire controller or just specific methods within your controller.
Examples:
[Authorize(Roles = "Administrator")]
public class AdminController : Controller
{
//your code here
}
or
public class AdminController : Controller
{
//Available to everyone
public ActionResult Index()
{
return View();
}
//Just available to users in the Administrator role.
[Authorize(Roles = "Administrator")]
public ActionResult AdminOnlyIndex()
{
return View();
}
}
Alternately, you can write a custom Authorize attribute to provide your own logic.
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
IPrincipal user = httpContext.User;
var validRoles = Roles.Split(',');//Roles will be a parameter when you use the Attribute
List<String> userRoles = GetRolesFromDb(user);//This will be a call to your database to get the roles the user is in.
return validRoles.Intersect(userRoles).Any();
}
}
To use:
[CustomAuthorizeAttribute(Roles = "Admin,Superuser")]
public class AdminController : Controller {
}
If iyou are using a post use
[Authorize]
[ValidateAntiForgeryToken]
If iyou are using a get use
[Authorize]
You can also use this custom attribute
public class HttpAjaxRequestAttribute : ActionMethodSelectorAttribute
{
public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
{
if (!controllerContext.HttpContext.Request.IsAjaxRequest())
{
throw new Exception("This action " + methodInfo.Name + " can only be called via an Ajax request");
}
return true;
}
}
Then decorate your action as below
[Authorize]
[HttpAjaxRequest]
public ActionResult FillCity(int State)
{
//code here
}
Remember to "Mark/Tick" if this solve your problem.
It depends on what type of session mechanisam you are using . Are you using default membership provider ? If not than you can pass user's id and sessionid make sure that user session is valid and user has required permission to make that call .
Along with the Authorize attribute, you can also allow only Ajax requests using custom attributes as shown here.
Thanks

Resources