ASP MVC: Getting confused when implementing ASP MVC Security - asp.net-mvc

I am implementing the security part of an ASP MVC application and I am getting confused in how to implement a custom membership provider since there seems to be a lot of functionallity that I wouldn't use.
The application I'm porting usually managed the security through an object stored in session called "SecurityManager" which contained the current user and a form permission collection. Each item of this collection contains the permission per form of the logged user and permissions per field of that form (in case they were needed if not full control of the form is assumed).
However, when I see the methods of the MembershipProvider and the AuthorizeAttribute tag they assume that I will use roles which my application does not use, we just have permission groups which are just the permissions grouped together for certain user groups, but they tend to change in time.
So basically the only thing I would need would be something that when a request is made would check if the security manager is stored in session (if it is not the user is not authenticated and will be redirected to the login page) and then get that object from session and perform operation with it to know if the user can or cannot access the view.
What would be the best approach for this? I've read that bypassing the custom membership was not a good idea.

Update: I recently came up against this and figured out how to use the AuthorizeAttribute to do exactly as you wanted. My attribute, that verifies if the user is an administrator, works as follows:
public class AuthorizeAdminAttribute : AuthorizeAttribute
{
public bool IsValidUser { get; protected set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null) { throw new ArgumentNullException("httpContext"); }
// Make sure Forms authentication shows the user as authenticated
if (httpContext.User.Identity.IsAuthenticated == false) return false;
// Retrieve the unit of work from Windsor, and determine if the current user is an admin
var unitOfWork = Bootstrapper.WindsorContainer.Resolve<IUnitOfWork>();
var user = new UserByIdQuery(unitOfWork).WithUserId((int)Membership.GetUser().ProviderUserKey).Execute();
if (user == null)
return false;
// Otherwise the logged in user is a real user in the system
IsValidUser = true;
return user.IsAdmin;
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext == null) { throw new ArgumentNullException("filterContext"); }
// If this user is a valid user but not an admin, redirect to the homepage
if (IsValidUser)
{
// Redirect them to the homepage
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
{
{ "area", "" },
{ "action", "Index" },
{ "controller", "Home" }
});
}
else
{
// User isn't logged in, perform normal operations
base.HandleUnauthorizedRequest(filterContext);
}
}
}
Essentially you have to user the AuthorizeCore() to determine if the user is logged in, store that result, and then perform authorization for the roles in your system. Then in your HandleUnauthorizedRequest you have to figure out if the request was unauthorized because the user wasn't logged in, or if it was because they weren't authorized.
Old Answer
I accomplish using the Authorize attribute by creating a subclass of the AuthorizeAttribute class. So for example:
public class MyCustomAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext == null) { throw new ArgumentNullException("httpContext"); }
// Make sure Forms authentication shows the user as authenticated
if (httpContext.User.Identity.IsAuthenticated == false) return false;
// replace with whatever code you need to call to determine if the user is authorized
return IsUserAuthorized();
}
}
Now when a controller or action is called, and is decorated with [MyCustomAuthorize] it will run this code to determine if the user is authorized based on your custom logic, and if not will redirect them exactly how the [Authorize] attribute would.
I don't know if this is the best approach, but it is what I came up with.

Related

Restricting access to action methods in controller in Asp.net MVC

I am new to Asp.net MVC web development and I developed one application using it. In my application I am using my own authentication and authorization check as follows:
I create Login controller in that created Login action method like this
[HttpPost]
public ActionResult Login(LoginViewModel Info)
{
if (ModelState.IsValid)
{
if (checking username and password exist in DB or not)
{
//Adding required values in session
Session["username"] = Info.Username;
//Redirect to dashboard
}
else
{
//not found redirect to login page
}
}
return View();
}
Now when accessing action methods in Admin controller I used my "custom authorize" attribute for checking user is logged-in or not and have rights for method
public class AdminController : Controller
{
[CustomAuthorize(ValidRole = "Admin")]
public ActionResult Index()
{
return View();
}
}
For this I override default AuthorizeAttribute like this
public class CustomAuthorize : AuthorizeAttribute
{
// Custom property
public string ValidRole { get; set; }
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext.Session["username"] == null)
{
//User is not logged-in so redirect to login page
return false;
}
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.Result = new RedirectToRouteResult(
new RouteValueDictionary(
new
{
controller = "Login",
action = "Login"
})
);
}
}
This code works fine for me. My question that is there any better solution for checking whether user is logged-in or not and according to it redirect user to login or dashboard page so that user can't manipulate url and get access to functionality to which he is not authorized.
thanks in advance
My question that is there any better solution for checking whether
user is logged-in or not and according to it redirect user to login or
dashboard page so that user can't manipulate url and get access to
functionality to which he is not authorized.
Yes, there's already a built-in method for doing this that does not rely on ASP.NET Sessions. It is called Forms Authentication.
You don't need to be writing any custom Authorize attributes. Once you verified the credentials of the user simply set the FormsAuthentication cookie:
if (checking username and password exist in DB or not)
{
// Emitting forms authentication cookie
FormsAuthentication.SetAuthCookie(Info.Username, false);
//Redirect to dashboard
}
and then simply use the built-in Authorize attribute to decorate your protected controller actions:
public class AdminController : Controller
{
[Authorize(ValidRole = "Admin")]
public ActionResult Index()
{
// At this stage the user is authenticated and has the role Admin.
// You could get the current username using the User.Identity.Name property
return View();
}
}
Forms Authentication is stateless. It does not rely on any state on the server to track the currently authenticated user on the server. The information about the current user is contained in an encrypted forms authentication cookie that is sent along each request. This way you don't need to be thinking about handling complex scenarios when your application is hosted in a web farm in which case you would have needed to use distributed ASP.NET Sessions.

User specific information accessible everywhere. How to secure it?

Using ASP.NET MVC 5 and Entity Framework. How can I secure my application so I cant access other users data?
To do CRUD stuff I have index, create, edit, delete methods in FooController so I can use:
/Foo/
to view my information I click one and get
/Foo/Details/5
When I type in 3 in the browser I get someone else's information.
/Foo/Details/3
How can I secure this from being accessed everywhere? I use Owin Identity and are logged into the application.
You could write a custom authorization filter by deriving from the AuthorizeAttribute class and inside you could check whether the currently authenticated user has access to the requested resource.
For example:
public class MyAuthorizeAttribute: AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
bool authorized = base.AuthorizeCore(httpContext);
if (!authorized)
{
return false;
}
string id = httpContext.Request["id"];
string currentUser = httpContext.User.Identity.Name;
return HasAccessToResource(id, currentUser);
}
private bool HasAccessToResource(string id, string currentUser)
{
// You know what to do here => check in your backend whether the
// current user is authorized to access the specified resource id
throw new NotImplementedException();
}
}
and then decorate your controllers/actions with this custom attribute:
[MyAuthorize]
public ActionResult Delete(string id)
{
// if you get that far, the current user is owner of the requested resource
...
}

How to restrict access to certain actions in controller in ASP.net MVC

I am new to ASP.net MVC and created my first web application using it. In my application I am using database authentication. I have created Login action in controller which checks entered username and password exist in DB or not, If it exist then put required values in Session and redirect user to pages as per his rights else redirect user to login page. Like this
public ActionResult Login()
{
if(uservalid)
{
//set session values and redirect to dashboard
}
else
{
//redirect to login
}
}
In my application there are some functionality that can only be accessed when user is logged-in. I want to check whether user is logged-in or not before user try to access these functionality and if he is not logged-in or not have rights then redirect to login page or show some error message.
public ActionResult SomeAction()
{
//Available only when user is logged-in
}
So how do I check whether user is logged-in or not and give access to action. I read about Authorize attribute but don't know how to use it as I am using database authentication.
If you are using FormsAuthentication you don't need to use ASP.NET session to track the currently authenticated user.
I read about Authorize attribute but don't know how to use it as I am
using database authentication.
Assuming you went with FormsAuthentication, once you have validated the credentials of the user you should set a forms authentication cookie:
public ActionResult Login()
{
if(uservalid)
{
FormsAuthentication.SetAuthCookie("username", false);
return RedirectToAction("SomeProtectedAction");
}
else
{
//redirect to login
}
}
and then:
[Authorize]
public ActionResult SomeAction()
{
string currentlyLoggedInUser = User.Identity.Name;
}
By the way if you create a new ASP.NET MVC application using the internet template in Visual Studio you might take a look at the AccountController which is responsible for authenticating users and setting forms authentication cookies. Of course you could throw all the Entity Framework crap out of it and implement your own credentials validation against your own database tables.
I apply [Authorize] as well as my own customattribute for restricting the action based on permission. The code is below
[Authorize]
[FeatureAuthentication(AllowFeature=FeatureConst.ShowDashboard)]
public ActionResult Index()
{
}
Filter code
public class FeatureAuthenticationAttribute : FilterAttribute, IAuthorizationFilter
{
public FeatureConst AllowFeature { get; set; }
public void OnAuthorization(AuthorizationContext filterContext)
{
//var featureConst = (FeatureConst)filterContext.RouteData.Values["AllowFeature"];
var filterAttribute = filterContext.ActionDescriptor.GetFilterAttributes(true)
.Where(a => a.GetType() == typeof(FeatureAuthenticationAttribute));
if (filterAttribute != null)
{
foreach (FeatureAuthenticationAttribute attr in filterAttribute)
{
AllowFeature = attr.AllowFeature;
}
User currentLoggedInUser = (User)filterContext.HttpContext.Session["CurrentUser"];
bool allowed = ACLAccessHelper.IsAccessible(AllowFeature.ToString(), currentLoggedInUser);
// do your logic...
if (!allowed)
{
string unAuthorizedUrl = new UrlHelper(filterContext.RequestContext).RouteUrl(new { controller = "home", action = "UnAuthorized" });
filterContext.HttpContext.Response.Redirect(unAuthorizedUrl);
}
}
}
}
you should create a basecontroller and inherit other controlers from base controller and then check whether the session is null or not to authenticate users.
public class BaseController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (Session["User"]== null)
{
filterContext.HttpContext.Response.Redirect("/somepage");
}
}
public class SomeController : BaseController
{
}
There are multiple ways of doing it but the preferred way would be to use the Annotation. Here is a post for it
How to get custom annotation attributes for a controller action in ASP.NET MVC 4?
If you are getting started I would suggest to follow the tutorial on
http://www.asp.net/mvc

How use another database and session to authorization?

I'm building a Asp.net MVC3 aplication (with Razor) and I have a Data Base that have information about users and roles.
This is simplified scheme of my DB.
User(IDUser, Login, Password);
Role(IDRole, Name);
UserInRole(IDUser, IDRole); //Many to Many
Looks like this:
I read about use AuthorizeAttribute, to control pages for loged users, and with specific roles and I research about use My DB to control users and roles. So my questions is:
Is possible use my DB to manage users and roles and use [Authorize] in my actions? [If yes how i do that?]
Is possible use session in the place of cookie to manage login and use the Authorization native Asp.net MVC3? [if yes, how i do that? if no how use session otherwise?]
If possible please post code examples.
Not sure if I understood correctly, but you want to use the [Authorize] attribute to work with your custom users database?
If that's the case, there are somethings to check:
To simply allow/deny based whether the user is authorized or not, the stock [Authorize] attribute will work just fine. The custom logic goes in your Login action, where you will check the database with the given credentials and issue the cookie accordingly. Something like:
public ActionResult Login(string username, string password)
{
bool isValid = //check the database with the given username and password
if(isValid)
{
FormsAuthentication.SetAuthCookie(username, false);
return RedirectToAction("...");
}else
{
return View();
}
}
If you want to also control access based on roles, I would say there are 2 immediate ways:
Implement a custom Membership and Role providers, something I don't like as I find them pretty useless, and always end up redoing the logic in my respositories
Implement a custom AuthorizeAttribute, like
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
//Check based on these 2 properties:
// this.Roles
// this.Users
//against httpContext.User
//return true or false to indicate access or deny
}
}
Thanks Pedro. Based in your post I build this to use SESSION:
public class CustomAutorizeAttribute : AuthorizeAttribute
{
public List<string> Roles { get; set; }
public CustomAutorizeAttribute()
{
}
public CustomAutorizeAttribute(params string[] Roles)
{
this.Roles = new List<string>();
this.Roles.AddRange(Roles);
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
User user = (User)httpContext.Session["user"];
if (user != null)
{
if (Roles != null)
{
foreach (var role in user.Roles)
{
if (Roles.Exists(e => e == role)) return true;
}
return false; // User don't have any hole
}
else
{
return true; // The Attribute is used without roles.
}
}
else return false; // Not logged.
}
}
Post here to hope others.

ASP.NET MVC 3 determine session status (new or timeout)

I currently use the default forms authentication method for my ASP.NET MVC application.
above all of my actionmethods that require authentication I have this attribute
[Authorize()]
When someone tries to call the page that that action method "serves" and they haven't yet logged in, it sends them to the login page...perfect! However, if their session times out and they try to hit that page, they're also just redirected to the login page with no indication of why. I'd like to be able to determine if it's a new visit, or if it's a timeout and display a different message on the login screen accordingly.
Is that possible?
Have a look at this custom authorize attribute i have made. It was to implement some custom role based authorization, but you could make it work for you as well. There is a Session.IsNewSession property you can check to see if this request takes place on a new session.
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if (httpContext.User.Identity.IsAuthenticated)
{
httpContext.User = new GenericPrincipal(httpContext.User.Identity, AdminUserViewModel.Current.SecurityGroups.Select(x => x.Name).ToArray());
}
return base.AuthorizeCore(httpContext);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (filterContext.HttpContext.User.Identity.IsAuthenticated)
{
filterContext.Result = new RedirectResult("/Authentication/NotAuthorized", false);
}
else
{
if (filterContext.HttpContext.Session.IsNewSession)
{
// Do Something For A New Session
}
base.HandleUnauthorizedRequest(filterContext);
}
}
}
On sign-in, you can set a cookie that's tied to the browser session. If that cookie exists, you know that the session timed out. If not, you know it's a new visit.

Resources