ASP.NET MVC 1.0 Authentication - asp.net-mvc

I realise that I can prevent unauthenticated users from accessing views at controller level by applying the [Authorize] attribute and can also filter views down to individual users or roles using this. However, my question is regarding doing the opposite... Is there a way to deny authenticated users from certain views without having to manually add in checks to see if they're authenticated in the opening lines of the controller code? Ideally an [Unauthorized] attribute or an equivalent if such a thing exists?
The reason for this is that I don't want authenticated users to be able to visit the account creation pages of the site I'm working on, as well as other resources. I realise I could check them in the controller explicitly but I'd prefer to decorate the controller methods if at all possible.
Thanks :)

This is along the lines of what LukLed was referring to:
public class UnAuthorizedAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
bool excludeCondition = false;
if (excludeCondition)
filterContext.Result = new HttpUnauthorizedResult();
else
base.OnAuthorization(filterContext);
}
}
Simply put in the logic for your excludeCondition. You can also to choose to do things like redirect to other views. Just mark your code with [UnAuthorized]

You can write your own authorization filter. Inherit from FilterAttribute and implement IAuthorizationFilter. Call it UnauthorizedAttibute and you will be able to use it like [Authorize].
Hear You can read about filters:
http://www.asp.net/LEARN/mvc/tutorial-14-cs.aspx

A simple way to accomplish this? Just leave the action untagged, and start with:
If(Request.IsAuthenticated)
// redirect somewhere, or return another view...

this could also be accomplished fairly simply if you are already using a roleprovider. then your actions would just need to be filtered by the appropriate role:
[Authorize(Roles = "Admin, Editor")]

Related

Prevent Url Tampering to access another users data

I just wanted to gauge opinions on how I should approach this problem and ultimately looking for a quick win (wrong way to think about things nut time pressures mean I have to think and act quickly!
I've been given a website that has a bit of an issue.
I login using standard forms authentication as User1234 and my url is as follows:
www.mywebsite.co.uk/1234/Contact.
This will take me to User1234's details.
You can put two and two together and correctly assume that 1234 is a user id of some sort.
Once authenticated, I can access the views with [Authorize] attribute present, any anonymous/unathenticated users get redirected.
However, once logged in as User1234, I can then tinker with the url like so:
www.mywebsite.co.uk/1235/Contact.
So I am authenticated as User1234 but can see User1235's data. This is BAD for obvious reasons.
When I log in, I actively set the login ID in session so in theory, I could do a check whenever a user hits an ActionResult, I could cross check the ID present in the URL against the session login ID. However, it is a rather project with lots of action results and as such, I'm reluctant to spend my Saturday afternoon adding something to each and every ActionResult.
Is there an event in the global.asax I could use that is hit on each ActionResult request where I can compare Session login ID with url ID?
Alternatively, can anyone offer some suggestions about how I can achieve this or restrict URL tampering?
You can try and do a base controller
public class BaseController : Controller
{
protected override void OnActionExecuted(ActionExecutedContext filterContext)
{
//Do your stuff here
base.OnActionExecuted(filterContext);
}
}
I assume that you don't want to change your URL routes, as you could retrieve the user id also from the session. A quick solution would be to use an ActionFilter which you can place on the affected controllers or action methods:
public class VerifyUserIdAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var sessionUserId = filterContext.HttpContext.Session["UserId"];
var routeUserId = filterContext.RouteData.Values["UserId"];
if (routeUserId != null && sessionUserId == routeUserId)
filterContext.Result = new RedirectResult("<<url to redirect to>>");
}
}
I don't understand why the URL contains a data entry point. This appears to be a design flaw. I would remove all code that uses a URL parameter and instead make sure the controller looks up what the ID is based on the logged in user.

What is Webform's "UrlAuthorizationModule.CheckUrlAccessForPrincipal" equivalent for MVC?

I got a problem as i am writing a custom SSO solution for my company. To mkae it simple, i've made a custom authentication httpmodule that intercepts all requests so as to check user authentication state. If not authenticated, user is redirected to my custom sso login page.
The thing is, when user is not authenticated, i'd like to check if he can access the requested page/resource... With Webforms, no problem, i add an authorization block in web.config, and i use UrlAuthorizationModule.CheckUrlAccessForPrincipal with an anonymous user. Everything works fine...
But when i apply my module to an MVC (3) web site, this does not work anymore (for obvious reasons, like the possibility to access the same controller and/or action from differents urls when using routing, and because authorizations are made through controller attributes).
How can I achieve this ?? I've been searching all day long, didn't find anything about that :/
ASP.NET MVC 3 Internet Application template includes a basic AccountController which implements the following actions (along with the associated models and views):
LogOn
Register
ChangePassword / ChangePasswordSuccess
You simply need the [Authorize] attribute on the Actions or classes you wish to secure. But if you need something really custom you can do something like I've done.
I created a custom class to override security in my application.
public class AuthorizeActivityAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
HttpContext currentContext = HttpContext.Current;
//Do your custom authentication stuff here and return true or false depending on results
Return true;
}
}
And now in my Controller I have the following:
[AuthorizeActivity]
public ActionResult Index()
{
ViewBag.Message = "Welcome";
return View();
}
I had the same problem.
See solution here: MVC equivalent of Webforms "UrlAuthorizationModule.CheckUrlAccessForPrincipal"
You would have to read the information from the other controller. This
can be done by instantiating its context and the Descriptor, then
instantiating the AuthorizationContext for that controller and read
the filter info.

Designing MVC Crud with Modal problem (Not allow direct acess to Create action)

I´m have a Car View with a list of car... So, I have a Create button that opens a Modal (UI JQuery Dialog) with Site/Car/Create content...
All works fine... But I´d like to block direct access to : Site/Car/Create...
Is that possible? How?
Thanks
It's not really possible to block it completely, but you can do some things to make it more difficult. First, require that it come from a POST request. That will prevent someone from simply entering the URL with request parameters. Second, use the antiforgery token helper. That will help prevent a third-party from doing a POST to the url since they will also require both the token input and the token cookie. Third, you could potentially check if the request has the X-HTTP-REQUESTED-WITH header and only do the POST (or GET) via AJAX. It's not that hard to get around but it would prevent an accidental access if you do use GET. Fourth, and it probably should have been first, make sure that only authorized users have access to the action using the AuthorizeAttribute. Fifth, use SSL to prevent unauthorized access using FireSheep and protect your cookies and data from snooping.
In short, you won't be able to prevent a determined person with legitimate authorization from crafting a request to the action if they a really want to without using your interface. They can always craft a request that will look exactly like the one you would send. You can make it more difficult and prevent accidental access, though, using the above methods.
[AttributeUsage(AttributeTargets.Method)]
public class AjaxOnlyAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAjaxRequest())
{
filterContext.HttpContext.Response.StatusCode = 404;
filterContext.Result = new HttpNotFoundResult();
}
else
{
base.OnActionExecuting(filterContext);
}
}
}
And then stick on your Create action like this:
[AjaxOnly]
public ActionResult Create()
{
...etc
}

How can I Implement a Custom RoleProvider?

I'm trying to implement a custom RoleProvider in my ASP.NET MVC application.
I've created a custom MembershipProvider and it works, in that I'm able to successfully validate the user. The next step is to implement the RoleProvider to restrict access to certian Controllers to Admin users only.
Can anyone provide me with a quick outline of the steps I need to take?
The point that I'm at now is I have my controller with the Authorize filter, like so:
[Authorize(Roles="Admin")]
public class AdminOnlyController : Controller
{
// stuff
}
and I have my CustomRoleProvider class, with the following method along with a load of not-implemented Methods:
public override string[] GetRolesForUser(string username)
{
if (username == "dave")
{
return new string[] { "Admin" };
}
}
I think I need to add the user to the Role somehow but I don't know how to do that. Ideally the end result would be a scenario where unauthorized users can't access certain controllers, and I in my Views I could determine whether to show links with something like:
if (User.IsInRole("Admin"))
{
// show links to Admin Controllers
}
Can anyone point me in the right direction?
I used this as as base line for a custom role manager: http://davidhayden.com/blog/dave/archive/2007/10/17/CreateCustomRoleProviderASPNETRolePermissionsSecurity.aspx
Should work in MVC or Web Forms.
UPDATE: Since that web page no longer exists, you could try this one instead. The basic requirements are that you need to implement the RoleProvider interface, namely:
void AddUsersToRoles(string[] usernames, string[] roleNames)
string[] GetRolesForUser(string id)
bool RoleExists(string roleName)
For the not-implemented methods, be sure to throw a NotImplementedException. This should help you figure out which methods are needed in your custom provider to get the job done.
I suspect you'll have to implement IsUserInRole.

ASP.NET MVC: Custom parameters to login page after authorization

I would like to redirect visitors to a login page with added parameters (based on the action they are performing) after the authorization fails.
This is an example of what I would like to do:
ASP.NET MVC - CustomeAuthorize filter action using an external website for loggin in the user
However, since this is a custom filter, I do not know how or if I can specify the Roles like in the usual authorization filter. I would like something like:
[CustomAuthorization(Roles="Admins")]
Thank you!
You could inherit from AuthorizeAttribute class and override OnAuthorize method like this:
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if (!HttpContext.Current.User.IsAuthenticated)
{
filterContext.Result = new RedirectResult("target");
}
}
Then you can use this custom filter just like AuthorizeAttribute.
Have you tried downloading the ASP.Net MVC source and taking a look at the AuthorizeAttribute's code (in AutorizeAttribute.cs)?
It might make sense to derive your CustomAutorization from the existing AuthorizeAttribute - check it out and see if you can tack on your required functionallity.
What about using just Request.Form in your custom Authorization class. It is just a POST call after all? Don't make it harder than it actually is.

Resources