ASP.Net MVC 3 Querystring Parameter - asp.net-mvc-3

I am developing an ASP.Net MVC 3 Web Application. Within some of my Views I display tabular data to the user, and beside each record in the table there is an Edit link. When the user clicks this link it takes them to an edit page where they can edit and update the record.
My issue is that once the user clicks the edit link, the URL becomes something like this
http://www.mytestsite.com/myData/edit/3
The '3' is the ID of the record to be updated, however, there is nothing stopping the user from changing the '3' to another digit, and this then means they can edit potentially a record which does not belong to them.
Does anyone have a solution on how I can prevent this from happening?
Thanks for you help.

You need to introduce Authentication and Authorisation into your application. Here is one article of many out there on how to get started with this. You will additionally need to work out how to store logged on user identity and then how to attach this to the record when it was created in the first place. You must then validate, on the server, that the subsequent edit request is being made by the user who created the record in the first place (or by a user who has a role on your system which allows them to do this, such as an Administrator).
Even if the ID wasn't being displayed on the URL a malicious user could still manipulate the HTTP Request to pass an ID of their choice. In any secure system you should always, always, always validate that the currently logged on user genuinely has permission to carry out the requested action. You should never rely on what comes back from the browser to determine this (aside from the authentication context which is managed securely by the MVC framework. Usually).

I believe you should have the information about who have the edit permission on this purticular resource, in your tables. Ex : in your table you might have the "CreatedById" column where you store the ID of the user who created this record. Now in your edit action method, you check the "CreatedById" of the current Item is same as of the "UserId" of the Current user (you maye get this from the session, if you stored it there). Something like this.
public ActionResult Edit(int id)
{
int currentUserID=1; // TO DO : get this value from session or somewhere
ProductVieWModel product=myRepo.GetProduct(id);
if(product!=null)
{
if(product.CreatedById==currentUserID)
{
return View(product);
}
else
{
return View("NotAutherized");
}
}
return View("ProdcutNotFound");
}

You should try using the GUID data type as it helps in these kind of situations, and the user cannot easily guess the next value

Related

Can CakePHP offer stricter user authentication (continuous throughout session)?

I am trying to create a suitable authentication check for a CakePHP service. Currently it appears that the user session is created initially during login, but never checked beyond this during a single session.
eg. Renamed the username, changing the password or ID in the user's database entry has no effect on the session.
Is there a preferred method for this type of, constantly checked, authentication? Essentially the user should be confirmed access at every request.
My current solution would involve extending the AuthComponent and storing a hash of the user data (including the encrypted password) and checking this at every request. I also considered storing the session ID in this same token, but noticed that CakePHP does not even use the session_start() function.
This functionality appears necessary for me, and I would have thought others would also require such a solution. I have yet to find Cake documentation or community solutions similar to what I need.
Well, you can use isAuthorized() function from AuthComponent. It's being called with every request.
public function isAuthorized($user){
return true; //allow the user to see the page
}
You can debug($user) to see the actual data and if you want "new" information from your database, you can always get them like this:
public function isAuthorized($user){
$current_user_from_database = $this->User->findById($user['id']);
if($current_user_from_database['User']['username'] != $user['username']){
$this->Session->setFlash('You\'ve changed the username. Please, login again.');
$this->redirect($this->Auth->logout);
return false;
}
return true;
}
Look at the API for more info and from the PDF book. You can look at this video about AuthComponent too. It's great.
If you need any more information or help, feel free to ask.
Btw. you have to configure AuthComponent in your Controller if you want isAuthorized() function to get called with every request.
If Session.timeout will work correctly with a setting of zero minutes, you're set. http://book.cakephp.org/2.0/en/development/sessions.html

Can I have multiple POST actions for an ApiController?

The scenario:
a User class has several groups of properties: password, address, preference, roles.
We need different Ajax calls to update the (1) user password, (2) user profile, (3) roles a user is in.
All the tutorials and examples only shows one POST action to update the whole User class. My question is how we can update only part of the class.
For example, when updating the user password, we will:
Display a text box to collect new password from user input.
Make an Ajax call that only POST the new password together with the userId (like: {id=3, newPassword=xxxxx}) to the WebAPI POST action.
That action will only update the password for the user.
One solution: (the easiest to think of)
Call the GET action with the userId to retrieve all the data for a user
Update the password in the user data with the values obtained from the web user input
Call the POST action with the updated data, which contains all properties in the User class.
That POST action will update the whole data without knowing only the password is changed.
The benefit: only one POST action is needed for the ApiController.
The shortcoming: we have to Ajax twice.
So, is it possible that we can have multiple POST actions in one ApiController? For example, PostPassword(userId, password), PostProfile(userId, profile) and PostRoles(userId, roles).
In this way, we will only call PostPassword to send the password to ApiController. In client side, there will be only one Ajax call. It is on the server where we will do the update. The benefit is of course the reduced data transferred over Internet.
If it is possible, what is the correct way to direct all different POST calls to their corresponding actions in the ApiController?
Please help us. Thank you all.
Most of cases, needless to have muptile post actions, I think. The typical case is consumer needs to edit user. So, s/he needs to load user data first to show on the edit form. After editing, consumer can click Save button to submit data and call POST action on api controller.
If your case is different, you should have nullable property for value type, and then the logic which should be checked in controller is if any property is null, it should not update this property into database.
You can only have one post action per controller action name. That is, you cannot do
// NOT VALID:
public ActionResult UpdateUser(string newPassword) { }
public ActionResult UpdateUser(List<string> newRoles) { }
However, parameters of the action can certainly be nullable. If a given property is not supplied in a given HTTP request, the value of the property in the controller would be null.
// VALID:
public ActionResult UpdateUser(string newPassword, List<string> newRoles)
{
if (newPassword != null) { } // It must have been supplied
if (newRoles != null) { } // It must have been supplied
}
Alternatively, you can have related controller actions that each handle one of your use cases, e.g. UpdatePassword(...), UpdateAddress(...), ...

MVC3 application and keeping track of what page the user initially entered

and thanks for taking the time to read my question. We will have visitors to the site that might arrive at another user's profile page. We will then encourage them to login to the site, or register as new if they are not currently members. These actions move them pretty far away from that initial page/URL they stated on, but we want to be able to "jump them" back to that page after completing login/sign-up by "keeping track" where they began. (NOTE: we're using the standard Microsoft membership provider classes, if it matters.) The "jumping back" part seems straightforward, it is the "keeping track" part that is the problem.
An illustration/example:
A visitor arrives at the site after clicking: www.mysite.com/profiles/ID=108
The visitor then leaves that page to login. How can we best capture the ID=108 somehow, so that there is a good option for the (logged-in) user to return to that profile page? I understand from reading that cookies are not optimal, but some of the other options seem to throw a monkey wrench into my thinking since the user is not yet logged-in, etc.
Any concrete steps that I can take to address this in the best MVC3 way?
EDIT:
public ViewResult MyProfile(int? id)
{
HttpCookie cookie = new HttpCookie("MySiteCookie");
cookie.Value = id.ToString();
cookie.Expires = DateTime.Now.AddYears(1); //or whatever time is appropriate
System.Web.HttpContext.Current.Response.Cookies.Add(cookie);
//do some other stuff
}
At the other end, to make use of the cookie, I've put it into the menu (temporarily) in such a way:
var MyProfileId = "";
if (Request.Cookies["MySiteCookie"] != null)
{HttpCookie cookie = request.Cookies["MySiteCookie"];
MyProfileId = Server.HtmlEncode(cookie.Value);}
and then you put it into your link
You have a couple of options:
1) You can use Session in your Controller to store the value:
Session.Remove("ID");
Session.Add("ID", "108")
And retrieve in the called Controller.
ID = Session["ID"];
2) You can pass the ID=108 on the query string from the Login Controller:
return RedirectToAction("Edit", "Profile", new { ID = "108" });
I understand from reading that cookies are not optimal
IMHO cookies are the best way to approach this. When an anonymous user lands on the profiles page simply emit a cookie containing the id of the profile that he is currently viewing. Then later when he successfully logs in read this cookie value to obtain the id and construct the redirect link and redirect him to this link.
Another possibility is to use server side session but I am mentioning this just as an alternative to cookies and not at all as something that I would recommend.
You can make the redirection to the login action adding a Url to a query string param.
Let say: www.mysite.com/login?ReturnUrl='www.mysite.com/profiles/ID=108'
I think that this is the default membership provider behaviour, but you can get the ReferrerUrl to place it in the query string on your own.

MVC 3 Page navigation security rules

I have a MVC3 application which follows PRG pattern, I am looking for a best way to define navigation rules to my application. For example I have application with pages A, B, C and D. Lets say A is a logon page. After user logon successfully, user will be redirected to page B. Now I do not want let the user to type url of page C in the address bar and get access to page C (Page C should be accessible only after POST ing page B or from Page D back button) I have to setup similar rules for all other pages as well (lets say when user is in page D, should not allow them to get into Page B)
currently I have one option where I can check the #Request.UrlRefferer property to get the source of the every request and decide which page to redirect to. I am not sure this is a best solution.
Appreciate your feedbacks!!
Do not base your security on this. Use the [Authorize] attribute to define security. The UrlReferrer can easily be forged as well.
Why are you trying to limit this? If you have a business reason the user most go through a particular flow, then consider either a cookie, session, or database entry to note their current 'completion' status - IE some somewhat persistent method to determine this. You could also form a token based on say - a session id - that gets passed into each page. If the token exists and matches the user's current session , then load the page for them. Of course this could be forged if the user understands this - but if you are simply trying to ensure the proper flow then this is a way as well. The user would not get a link with the current session id in it until they hit the prior step.
If you don't want a particular page to be accessible via the URL, one option available is to make sure there's no way to access the page via a URL. To access the page, make a POST action that will return a view rather than a redirect. This would mean the view your POST action returns will be shown on a page with the URL of the previous page. For exameple:
Page A URL is /login and after logging in, the user is redirected to Page B. The URL is now /home. Page B sends a POST request and the contents of the page becomes Page C but the URL still remains as /home. The only way to view the contents of Page C would be to visit Page B and send a POST request.
This breaks the PRG pattern but that's one option.
There is one more alternative, store the current permissions of the user indicating which page they're allowed to enter and check if the user is authorized to view a page before executing the action. You could place the code in an ActionAttribute which you can apply to your action methods or entire controllers. If you'd like a more detailed explanation of this technique, leave me a comment and I'll write up another answer describing this technique in more detail.
Here's a quick proof-of-concept of the technique described above:
public class PermissionsNeeded : ActionFilterAttribute
{
string expectedPermission;
public PermissionsNeeded(string permission)
{
expectedPermission = permission;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
var currentPermissions = filterContext.HttpContext.Session["CurrentPermissions"] as IEnumerable<string> ?? new List<string>();
// If user does NOT have permission to access the action method
if(!currentPermissions.Contains(expectedPermission)
{
throw new HttpException(403, "User is not authorized to view this page");
}
}
}
class YourController : Controller
{
[HttpPost]
public ActionResult PageB()
{
var currentPermissions = Session["CurrentPermissions"] ?? new List<string>();
currentPermissions.Add("PostedFromPageB");
Session["CurrentPermissions"] = currentPermissions;
return RedirectToAction("PageC");
}
[PermissionsNeeded("PostedFromPageB")
public ActionResult PageC()
{
return View();
}
}
Currently, the custom attribute will only accept one permission at a time which is a simply limitation to rectify. You'd be responsible for removing the permissions stored in the Session when you feel the user shouldn't have certain permissions anymore. I threw an HttpException that return a 403 status code (unauthorized access) but if you'd instead like to return an ActionResult such as a RedirectToRoute or a View, you could set a value to the filterContext.Result property.
I end up doing this task as below:
On successful completion of every page, save the page Name in database
When user request for a new page, simply check the page they have completed last from database and decide what to do.
I chooses this approach simply because it will definitely help during Problem Solving/Troubleshooting once application is in Production, which is huge for me.
Thanks everyone for your responses!

codeigniter permissible user actions

hi typically a codeigniter mvc controller accepts an id as a parameter for a controller function. For example:
/photo/edit/1
A user would edit image id 1 from the photo controller. What is the best practice to prevent a user from editing someone else’s image..for example editing id 2? Restriction has to include more than just verifying a logged in user, because a logged in user will still be able to edit image 2.
I was thinking that i would write a library that implements a permission function, that is called on all controller functions. I would pass the user id and the url to the library function which would contain logic to verify if a user could execute that function or in this case edit an image.
The problem i see is..it will be tedious to write the logic code for all functions of my site, as each is different logic. Is there a better generally practiced way?
You generally handle the checking in the controller itself, so if, for instance you have the currently logged in user, and the photo object from the db, just store the photo's owner in the db record and compare them.
It really is not all that tedious, you are simply verifying ownership of the object before processing actions on it.
example...
if ($the_user->id == $the_photo->owner_id) {
//allow their actions
}
else {
redirect('/'); //if not, kick em out
}

Resources