Security approach in web application
Asked Answered
F

3

6

I am designing a web application in ASP.NET / C# where each registered user has the ability to add/modify/delete rows based on their user-id.

Take this example:

I am going to edit my route on the page /route.aspx?routeid=854 which belongs to me (user-id: 1).

But because I am a curious guy I try to access /route.aspx?routeid=855 which belongs to another user (user-id: 2).

How can I best avoid people from accessing other peoples data? Should I send each user id (from session) with each database-call, should I validate user/password on every page load or what is the best and most secure approach?

I hope I made this clear enough.

Fold answered 18/5, 2010 at 9:48 Comment(0)
T
3

DON'T REINVENT THE WHEEL

Edit: Storing UserId - you don't have to. You can get it from the MembershipProvider at any time as long as the user is logged in of course:

MembershipUser user = Membership.GetUser();
Guid UserID = user.ProviderUserKey;

Sounds to me like you need to implement the ASP.NET Membership Provider. Have a read of this resource: http://odetocode.com/articles/427.aspx

Also, a good series from Scott Guthrie: http://weblogs.asp.net/scottgu/archive/2006/02/24/ASP.NET-2.0-Membership_2C00_-Roles_2C00_-Forms-Authentication_2C00_-and-Security-Resources-.aspx

In general, take this approach: Use forms authentication to validate who a user is. This is the Authentication side of security. That is, determining the user is who they say they are, usually with a username and password.

The second part of security is Authorisation, which happens once you know who the user is. This basically consists of determining which resources an authenticated user has access to. A mature system will include the following entities:

User: may contain extended profile information captured on registration
Resource: a page or other resource that can be restricted.
Group: a group of users who can access resources due to their group membership (groups are granted resource access)
Role: a type of user such as Administrator/Developer/Salesperson. 

Thus, to grant a user access to routeid 854 (a Resource) you could grant the resource directly to the user or if there are multiple users who should have acceses to that resource and those users form a natural group, then create that group, grant the resource to the group and add the user to the group.

Then you can access User.Resources by a resource id or you can protect a whole page using

if(!User.IsInRole("RoleName"))
{
  //redirect to access denied page
}

There are lots of good things available using the provider model.

Edit: Something to be aware of if you decide to store profile information about your users: The default implementation of the ProfileProvider is not particularly good. Scott Guthrie wrote a good article on a table based provider which is better: http://weblogs.asp.net/scottgu/archive/2006/01/10/435038.aspx

Trend answered 18/5, 2010 at 10:7 Comment(3)
I am using the ASP.NET MemberShip provider to do the login. But nice to see some info on the custom informations. :-) Going to read more of that..Fold
Good stuff: There is some good example code here too: asp.dotnetheaven.com/aspnet/doc/security/membership.aspx#authTrend
Regarding storing the UserId, look at the Edit at the top of my answer.Trend
A
3

Your best approach would be to send the userId to the database with the routeId to see if the user can access it.

something like:

select * from route where routeId=@routeId and userId=@userId

If you're using something like Linq you can make a much better security model by applying the user restriction like with a reusable function like this:

public Route Get(int routeId, int userId)
{
    var query repository.Get<Route>().Where(r => r.Id == routeId);
    query = applySecurityModel(query, userId);
    return query.FirstOrDefault();
}

private IQueryable<T> applySecurityModel<T>(IQueryable<T> query, int userId) where T : ISecurable
{
    return query.Where(t => t.UserId == userId);
}

public interface ISecurable
{
    int UserId { get; set; }
}

public class Route
{
    int Id { get; set; }
    int UserId { get; set; }
}
Alexalexa answered 18/5, 2010 at 9:52 Comment(4)
Where is the best way to store this user id? Session?Fold
And should I validate the current user corresponds to this user id on page load?Fold
Save the userID server side (e.g. in the Session object) and NOT client side (e.g. in a cookie).Staffman
Okay, I will store the ID in the session. Is it secure enough? Should I refresh the session on every page load to ensure the user id is there?Fold
T
3

DON'T REINVENT THE WHEEL

Edit: Storing UserId - you don't have to. You can get it from the MembershipProvider at any time as long as the user is logged in of course:

MembershipUser user = Membership.GetUser();
Guid UserID = user.ProviderUserKey;

Sounds to me like you need to implement the ASP.NET Membership Provider. Have a read of this resource: http://odetocode.com/articles/427.aspx

Also, a good series from Scott Guthrie: http://weblogs.asp.net/scottgu/archive/2006/02/24/ASP.NET-2.0-Membership_2C00_-Roles_2C00_-Forms-Authentication_2C00_-and-Security-Resources-.aspx

In general, take this approach: Use forms authentication to validate who a user is. This is the Authentication side of security. That is, determining the user is who they say they are, usually with a username and password.

The second part of security is Authorisation, which happens once you know who the user is. This basically consists of determining which resources an authenticated user has access to. A mature system will include the following entities:

User: may contain extended profile information captured on registration
Resource: a page or other resource that can be restricted.
Group: a group of users who can access resources due to their group membership (groups are granted resource access)
Role: a type of user such as Administrator/Developer/Salesperson. 

Thus, to grant a user access to routeid 854 (a Resource) you could grant the resource directly to the user or if there are multiple users who should have acceses to that resource and those users form a natural group, then create that group, grant the resource to the group and add the user to the group.

Then you can access User.Resources by a resource id or you can protect a whole page using

if(!User.IsInRole("RoleName"))
{
  //redirect to access denied page
}

There are lots of good things available using the provider model.

Edit: Something to be aware of if you decide to store profile information about your users: The default implementation of the ProfileProvider is not particularly good. Scott Guthrie wrote a good article on a table based provider which is better: http://weblogs.asp.net/scottgu/archive/2006/01/10/435038.aspx

Trend answered 18/5, 2010 at 10:7 Comment(3)
I am using the ASP.NET MemberShip provider to do the login. But nice to see some info on the custom informations. :-) Going to read more of that..Fold
Good stuff: There is some good example code here too: asp.dotnetheaven.com/aspnet/doc/security/membership.aspx#authTrend
Regarding storing the UserId, look at the Edit at the top of my answer.Trend
E
-1

This was my issue as well. Some solutions introduced by Mr. Keramati here.

But introduced solution id in Tamper-proof hidden fields in ASP.NET MVC:

You can encrypt critical property values in your model. You can create your own attribute and use it for action and attribute accept property name as an argument in an array of string and before send view to client.

All mentioned property value would be encrypted and when a form post data to action, attribute decrypt value and compare both original Value and Decrypted Value. If both was equal then data is correct and all data can be sent to database otherwise validation will fail. It is essential for PrimaryKey which is easily manipulated by client with inspect tools and other tools.

Ehrenberg answered 8/7, 2022 at 12:58 Comment(1)
NOTE: The answer has since been edited, thus is no longer a link only answerTerat

© 2022 - 2024 — McMap. All rights reserved.