Session or Profile Provider? - c#

The goal
Pick Session or ProfileProvider to brings to life some user's information.
The problem
Session and ProfileProvider are different things — they play different roles.
There are three information that I need to use all the time: the user's Fristname, Lastname and StoreId. The Firstname and Lastname will always be the same, but the StoreId can be changed — and I can't store its value within a cookie.
So I need to ask: based on this scenario, there's any problem to store those information (First/last name & StoreId) within a Session? Install and implement all the ProfileProvider's methods costs me too much time, and a Session can solve this quickly, but I need to know if there's something wrong to store first/last name in this way of data storage.
Too broad?
I think this question can share multiple opinions, but the proposal is very simple: can I store those three information within a Session? Actually I know that I can, but what I need to know is simpler: how much will this cost to me? Performance (How much/why?)? Security (How much/why?)?

Sure, of course you can. And I don't think that performance and/or security are an issue here (without knowing the details, that is). What's important is how long you want to store this data. If it's in a session, it'll be gone as soon as the user terminates the session (logs out). If that's fine for you, use session variables. If you need to know this data the next time the same user logs in, then the ProfileProvider is what you need, it does store data independent of any session.

Related

Check status of user during (server) interaction in MVC

I have somewhat of a thought problem, where I'm not sure if what I already built can be done a lot more efficiently, so that's why I'll share my 'problem' here. (to be clear, everything I have built works, I'm just looking to make it more efficient).
I have a webapp made with MVC & SQL which has a log-in system etc for users.
A user has a status, which is an enum, and can be active, blocked etc and is stored in the database (along with other user-data).
Within my webapp I have made a custom AuthorizeAttr. for authorizing users on every call made (applied as a global filter).
However, the 'normal' authentication is based on the cookie, which does not change when I would change the user-status in the database. For instance, users can de-activate another user in the same group (when being Admin). These database changes are not taking immediate effect since by default the authorization only verifies the cookie, and the cookie is based on the status when logging in.
To fix this issue, I added some additional logic to my authorizationAttr, which on every request calls the database for the current user status (the enum), and then simply does some checks whether the user is allowed to continue, or a redirect is required.
Calling the database on every request seems (even just for 1 enum) seems to be a bit taxing on the server/db especially when the webapp would grow in popularity (= lots of users).
One idea I thought of was to cache the enum in session cache but for short periods of time (like 60 seconds), this would save some database calls, but obviously the user can still use the webapp for max 60seconds after being de-activated.
I could be wrong in thinking that these database calls are actually that taxing of course.
Any ideas for improvement?
how do you know that checking status per request is too expensive? did you measure performance cost of checking user status in the database? have you created your custom cache without actually measuring the cost of simple solution? do you use ORM like hibernate? they have 2nd level cache built in so often there will be no roundtrip to the database.
i think it's way better to stick to the KISS principle rather than creating custom solution for a difficult problem. even if your database will be the bottleneck then usually buying additional hardware once is cheaper than maintaining overcomplicated solution for years
if your application grow, first thing you throw away is relation database
Have you considered using ADO.NET DataSets for your requirement? If you don't have multiple front-ends you could possibly read the login statuses initially into the dataset. All read/write operations could be made to this and you could later save your changes to the actual database. In case you have multiple front-ends, would it be possible for you to restrict all read/write/modify operations of one group to a single front-end instance? Because I guess you could use the dataset approach in that case as well.

are cookies the only way of storing session variables?

I want to store a user setting(language). so i can get the corresponding resources when the page loads. I figured cookies would be the way to go, but it's just not an option, too difficult since i have tried and tried without success.
After 2 days i want to give up on cookies and see if there is another way I can achieve the same goal
i've read this article http://msdn.microsoft.com/en-us/library/ms178581.aspx
but im not sure if I can achieve what I want using that.
What alternatives for cookies could i use in my situation?
Depending on the level of persistence you're looking for, there are a couple of other ways you can do this. The first is to use session to hold these settings. However, if you use session the settings will only live as long as the session does. If your website has some kind of authentication interface, you can store the settings in a database relative to the username used for authentication. If you don't have authentication involved and simply want to remember that the user came with a particular computer/device, you can achieve the same result by footprinting the system (not trivial) and storing that footprint in the database related to any settings it would encounter.
If those options are not available to you, then cookie will be your only remaining alternative.
An other alternative to using cookies to keep a session ID is to use cookie-less session management, which is mentioned in the article that you linked to. A cookie won't be kept on the client machine with the session identifier -- instead, it will be in the query string. It's definitely an "uglier" solution, but it's one of the few options you have. You can either keep a cookie that's sent up with each request, or stick something on the query string to identify the request.
Either way, you need some way for your server to pick up the identifier and retrieve your session data -- whether it's getting the ID from a known cookie or a known query string value.
I mean, there are probably other ways -- keeping a hidden value on each and every page, but I think that just gets even "uglier". You want to keep that information out of the page/information that you're rendering.

Exposing Database IDs to the UI

This is a beginner pattern question for a web forms-over-data sort of thing. I read Exposing database IDs - security risk? and the accepted answer has me thinking that this is a waste of time, but wait...
I have an MVC project referencing a business logic library, and an assembly of NHibernate SQL repositories referencing the same. If something forced my hand to go and reference those repositories directly from my controller codebase, I'd know what went wrong. But when those controllers talk in URL parameters with the database record IDs, does it only seem wrong?
I can't conceive of those IDs ever turning un-consumable (by MVC actions). I don't think I'd ever need two UI entities corresponding to the same row in the database. I don't intend for the controller to interpret the ID in any way. Surrogate keys would make zero difference. Still, I want to have the problem because assumptions about the ralational design aren't any better than layer-skipping dependencies.
How would you make a web application that only references the business logic assembly and talks in BL objects and GUIDs that only have meaning for that session, while the assembly persists transactions using database IDs?
You can encrypt or hash your ids if you want. Using session id as a salt. It depends on the context. A public shopping site you want the catalog pages to be clear an easily copyable. User account admin it's fine to encrypt the ids, so users can't url hack into someone else's account.
I would not consider this to be security by obscurity. If a malicious user has one compromised account they can look at all the form fields, url ids, and cookie values set while logged in as that user. They can then try using those when logged in as a different user to escalate permissions. But by protecting them using session id as a salt, you have locked that data down so it's only useful in one session. The pages can't even be bookmarked. Could they figure out your protection? Possibly. But likely they'd just move on to another site. Locking your car door doesn't actually keep anyone out of your car if they want to get in, but it makes it harder, so everyone does it.
I'm no security expert, but I have no problem exposing certain IDs to the user, those such as Product IDs, User IDs, and anything that the user could normally read, meaning if I display a product to the user, displaying its Product ID is not a problem.
Things that are internal to the system that the users do not directly interact with, like Transaction IDs, I do not display to the user, not in fear of them editing it somehow, but just because that is not information that is useful to them.
Quite often in forms, I would have the action point to "mysite.com/messages/view/5", where 5 is the message they want to view. In all of these actions, I always ensure that the user has access to view it (modify or delete, which ever functionality is required), by doing a simple database check and ensure the logged in user is equal to the messages owner.
Be very very very careful as parameter tampering can lead to data modification. Rules on 'who can access what ids' must be very very carefully built into your application when exposing these ids.
For instance, if you are updating an Order based on OrderId, include in your where clause for load and updates that :
where order.orderid=passedInOrderId and Order.CustomerId=
I developed an extension to help with stored ids in MVC available here:
http://mvcsecurity.codeplex.com/
Also I talk about this a bit in my security course at: Hack Proofing your ASP.NET MVC and Web Forms Applications
Other than those responses, sometimes it's good to use obvious id's so people can hack the url for the information they want. For example, www.music.com\artist\acdc or www.music.com\arist\smashing-pumpkins. If it's meaningful to your users and if you can increase the information the user understands from the page through the URL then all the better and especially if your market segment is young or tech savvy then use the id to your advantage. This will also boost your SEO.
I would say when it's not of use, then encode it. It only takes one developer one mistake to not check a customer id against a session and you expose your entire customer base.
But of course, your unit tests should catch that!
While you will find some people who say that IDs are just an implementation detail, in most systems you need a way of uniquely identifying a domain entity, and most likely you will generate an ID for that identifier. The fact that the ID is generated by the database is an implementation detail; but once it has been generated it becomes an attribute of the domain entity, and it is therefore perfectly reasonable to use it wherever you need to reference the entity.

How to hide a database ID from HTML/Javascript

Obviously depending on the type/context of data returned to a web front-end (in my case the setup is HTML/Javascript, .NET Csharp back-end and JSON as the data transport), if I have to return an ID say of a message that is an auto-generated primary key (Int64), what is the best way to "hide" this real ID?
For most things of course, I can understand it doesn't make too much difference, however an application I am working on means if a user "guesses" an ID in the URL to pull back another record, it could prove to be a security issue..
There seems to be lots of ideas/commentary about methods, but nothing has quite clicked.
I was thinking of having an auto-generated primary INT, but also a secondary alternate GUID too. It would be the GUID returned to any front-end process, and of course the auto-generated primary ID would still be used in the backend..
The thinking of course is the GUID would be far more difficult to guess/obtain another one to access a record?
Any ideas or best practices people use?
Thanks in advance,
David.
Regarding security you have several aspects:
Session hijacking
Accessing/Modifying/Creating/Deleting records the user is not authorized to
Non-Authenticated access
Cross-Site* attacks
Man-in-the-middle attacks
etc.
The measures to deal with these depend on your architecture and security needs.
Since you don't say much about your arhcitecture and security needs it is really hard to give any specific advice...
Some points regarding "ID shouldn't be guessable":
"Correct" solution
The problem goes away in the moment you implement authentication + autherization properly
because properly implemented these two make sure that only authenticated users can access
anything at all AND that every user can only access things he is allowed to. Even if an authenticated user knows the correct ID of something he is not allowed to access this would be secure because he would prevented from accessing it.
"weak solution"
create a ConcurrentDictionary as a thread-safe in-memory-cache and put the real IDs plus the "temporary IDs" (for example upon first record access freshly generated GUIDs) in there. You can combine that temporary ID with some salt and/or encryption and/or hash of some connection-specific aspects (like client IP, time etc.). Then on every access you check with the ConcurrentDictionary and act accordingly... one positive effect: after app restart (for example app pool recycling) the same record gets a different ID because this is only an in-memory-cache... though this is hardly usable in a web-farming scenario
I am working on means if a user "guesses" an ID in the URL to pull back another record, it could prove to be a security issue.."
If this is the case then you really need to step back and review the approach to security. If a user can access records which they don't have authorisation to view you do not provide appropriate security of your Object References - https://www.owasp.org/index.php/Top_10_2010-A4-Insecure_Direct_Object_References
The GUID approach will attempt to provide security by obscurity see Is using a GUID security though obscurity? as to whether or not it does you will have to make your own mind up based on your circumstances.
Ofcourse technically, pulling back another record by quessing another ID is a bad thing- only when that other ID shouldnt be visible for the user who's pulling it back. But then you have a security problem anyways and you should focus on that rather then find a way to obfuscate the ID
Anyways, if you want to mess up the url, i recommend you looking into Rijndael. We use it alot here to pass around tokens. Basically, this encryption technique allows you to both encrypt and decrypt. Therefore you can encrypt the ID, send it to the client, the client posts it back and you can simply decrypt again. No need for an extra database record. Even more secure is to encrypt/decrypt the record ID salted with something like an IP for the current client, therefore even URL fishing will be a reduced problem.
See: http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael.aspx
I would like to say that, the URL are meant to be public, it is not kind of confidential data. There's no need to hide the url from users. If a url can be seen by one user and should not be accessable to another user, you should check the privilege of the user from the server side instead of hiding that url.
All of the other answers (3) failed to cover the possibility of this being a non-cookied, non-authenticated, non-sessioned, non-logged-in user.
For example, a confirmation page after a order, etc...
In that case, your authentication is based on a secret in the URL. You use a secret that for all practical purposes is unguessable, and very unique per record. Then you assume that if the user has that secret, then they have access to said record, etc...
The real chalenge is to find a good way to make a secret UUID. Many developers will take the SHA1() of rand() + time() + uuid() + remote_ip() or something like that (which is typically sufficient), but I'm sure there is plenty of documentation out there on this.
Yes, in a situation where you have a non-authenticated user accessing a specific piece of data or performing an action (such as password reset), you need to have a second identifier (eg, varchar 40) on your records with a unique key (as you had outlined). Fill it with very random data, and if they have that secret, then let them in.
Take care.

Caching Active Directory Data

In one of my applications, I am querying active directory to get a list of all users below a given user (using the "Direct Reports" thing). So basically, given the name of the person, it is looked up in AD, then the Direct Reports are read. But then for every direct report, the tool needs to check the direct reports of the direct reports. Or, more abstract: The Tool will use a person as the root of the tree and then walk down the complete tree to get the names of all the leaves (can be several hundred)
Now, my concern is obviously performance, as this needs to be done quite a few times. My idea is to manually cache that (essentially just put all the names in a long string and store that somewhere and update it once a day).
But I just wonder if there is a more elegant way to first get the information and then cache it, possibly using something in the System.DirectoryServices Namespace?
In order to take control over the properties that you want to be cached you can call 'RefreshCache()' passing the properties that you want to hang around:
System.DirectoryServices.DirectoryEntry entry = new System.DirectoryServices.DirectoryEntry();
// Push the property values from AD back to cache.
entry.RefreshCache(new string[] {"cn", "www" });
Active Directory is pretty efficient at storing information and the retrieval shouldn't be that much of a performance hit. If you are really intent on storing the names, you'll probably want to store them in some sort of a tree stucture, so you can see the relationships of all the people. Depending on how the number of people, you might as well pull all the information you need daily and then query all the requests against your cached copy.
AD does that sort of caching for you so don't worry about it unless performance becomes a problem. I have software doing this sort of thing all day long running on a corporate intranet that takes thousands of hits per hour and have never had to tune performance in this area.
Depends on how up to date you want the information to be. If you must have the very latest data in your report then querying directly from AD is reasonable. And I agree that AD is quite robust, a typical dedicated AD server is actually very lightly utilised in normal day to day operations but best to check with your IT department / support person.
An alternative is to have a daily script to dump the AD data into a CSV file and/or import it into a SQL database. (Oracle has a SELECT CONNECT BY feature that can automatically create multi-level hierarchies within a result set. MSSQL can do a similar thing with a bit of recursion IIRC).

Categories