Restricting access to action methods in controller in Asp.net MVC - 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.

Related

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

Share Action with Authorized and Unauthorized User in ASP.NET MVC Controller

I have an ASP.NET MVC app that with a controller. All of the actions in this controller can be accessed by anonymous users. However, if the user is authenticated, I want to do something special in the action. Currently, I've noticed that no matter what, User.Identity.IsAuthenticated is always false in the context of this action. Here is my code:
public class MyController : Controller
{
public ActionResult GetProfile(string id)
{
if (User.Identity.IsAuthenticated) {
ViewBag.ShowAuthStuff = true;
} else {
ViewBag.ShowAuthStuff = false;
}
}
}
How do I make it such that both an authenticated and an unauthenticated user can access the same action, but do different things? I can't figure out why User.Identify.IsAuthenticated is always false. I checked my cookies. When I'm logged in, there is a cookie named:
.ASPXAUTH
However, when I visit the action, that cookie is no longer available.
Just use both Authorize and AllowAnonymous filters:
[Authorize]
[AllowAnonymous]
public ActionResult GetProfile(string id)
{
if (User.Identity.IsAuthenticated) {
ViewBag.ShowAuthStuff = true;
} else {
ViewBag.ShowAuthStuff = false;
}
}
Though it doesn't make a whole lot of sense to have anonymous access to a "profile".
Also, typically, you don't want to mix authorized and unauthorized actions in the same controller. It's better to have actions that must or may require authorization in a controller together, and unauthorized actions in a separate controller. In that case, you specify the Authorize filter on the controller itself, and then AllowAnonymous on any individual actions that want to interact with authenticated users, but don't require it.
For example in an "Accounts" controller:
[Authorize]
public class AccountsController : Controller
{
public ActionResult Profile()
{
// Login required to reach here
}
[AllowAnonymous]
public ActionResult Login()
{
if (User.Identity.IsAuthenticated)
{
// Already logged in, redirect to profile
return RedirectToAction("Profile");
}
// Show login form for anonymous user
return View()
}
}

ASP MVC: Getting confused when implementing ASP MVC Security

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.

Where is the best place to validate that a user is authenticated in asp.net mvc

I'm working in a application where I need to verified that request comes from authenticated users. Because I made a lot of loads base on user Guid.
Example
public ActionResult ManageEmployee()
{
var loadedEmp = GetLoadedEmp(GetLoggedUserGuid());
return View("Employee/Manage", loadedEmp);
}
My question is, do I need to do this "verified that the user is authenticated"
public ActionResult ManageEmployee()
{
if (!User.Identity.IsAuthenticated)
{
return View("Account/LogOn");
}
var loadedEmp = GetLoadedEmp(GetLoggedUserGuid());
return View("Employee/Manage", loadedEmp);
}
on every ActionResult function or is there a beast approach or centralized solution.
Thanks
Use the AuthorizeAttribute on the Action in the controller to require users to be logged in to perform said Action:
[Authorize]
public ActionResult ManageEmployee()
{
// This code will only execute if the user is Authenticated
var loadedEmp = GetLoadedEmp(GetLoggedUserGuid());
return View("Employee/Manage", loadedEmp);
}
When using that attribute, the user will be automatically redirected to the login page if they are not logged in (as long as your app is configured properly).
#Justin Niessner is right, but as a shortcut if you want an attribute to be applied to every action in your controller you can just put the AuthorizeAttribute on the class:
[Authorize]
public class HomeController : AreaController { ... }
I think that you also use this attribute to lock down on a specific roles and users - should you use the role provider functionality.

Resources