User profile in Session variable - asp.net

I've a pretty basic question related to user profile storage along a session.
Let's say that I've an Account table that stores user profiles and that I've linked this table to ASP.NET SimpleMembership. Once a user is logged in, controllers may need to retrieve information in or based from her Account. What I'm doing right now is querying the database each time I need data, with something similar to this: _dbContext.Accounts.Where(a => a.EmailAddress == User.Identity.Name).Single().
But I'm afraid that this may cause unnecessary load on the DB and think that a better idea (perhaps it's what everybody does!) is to store the Account object in a Session variable once a user logs in, enabling direct access without re-querying the DB.
Is this the usual way to do it? Isn't there a risk of "de-sync" between the Session variable and the authentication?
Thanks

Our website uses this same type of method for a user-type object at login. Upon confirmed login we store the user object in a session variable. If something is changed or updated the object is updated and depending on the circumstance the change is updated in the database as well (timing meaning update immediately following the change or, after gathering a group of changes).
It just depends on how complex your system is. Ours is fairly complex, and this has proved to be a pretty solid way - without requiring constant maintenence and updates.

Related

Not handling authentication, but need claims and cookie

I am creating a new asp.net MVC 5 application. Authentication is handled by a third party using smart cards. Once a user is authenticated by the third party, I am sent the user's unique ID (inside the http header) which I match up against my database in order to find relevant information about said user (roles, display name, etc.).
Currently, on every page request, the sent user ID is compared against the database, and checks are performed to ensure the user has the proper permissions to view the requested page. While this works, it sure seems like a bunch of needless database hits when all the user information could just be stored in a cookie.
If I was using Individual User Accounts for authentication, what I am looking to do would simply be built in using Identity and OWIN. But since I am not handling the authentication, but merely the authorization, is there a way to use all the nice features of Identity and OWIN (claims and cookies specifically)? If not, how might one go about this?
Also, of particular interest to me is when a role is added or removed. Using OWIN with Individual User Accounts, updating the cookie is as simple as logging the user out, and then back in immediately in the background. That functionality would also be desired for any solution presented.
Any insight would be extremely helpful. Thanks for reading!
You could do what you're asking by directly storing values in a custom cookie, but for your purposes it sounds to me like you might be more interested in utilizing sessions to track that info. This will keep all of your actual data stored server-side, which is more secure as it isn't vulnerable to cookie modification and it allows you more freedom to control the state (for your role example, you wouldn't have to "update" the cookie at all, just update the session variable on the server side to add or remove the role as needed).
Figured it out. Found a great article that really helped:
http://www.khalidabuhakmeh.com/asp-net-mvc-5-authentication-breakdown-part-deux

Get users security and info every request -> Else data gets stale

What we have currently implemented works well but I'm just concerned that there maybe a better way or we are doing it completely wrong.
Once logged into our website, on each and every request it will make a request to the API to get the users details.
E.g. Username, ImageUrl, Roles / Permissions, Email Address etc
It then stores this data in the BaseController for the viewpage or anyone else to see during that request.
Upside:
to doing it this way is that you know each request that the users permissions/roles and their details are all up to date!
Downside:
Your most likely to get exactly the same data every request, until that one day they change their details. Thus your possibly making unnecessary calls??
However the first way we tried all this was when the user logged in all their data gets stored in the cookie, the problem with this is that our users hardly ever logout so all the data that is stored in the cookie gets stale often. -> Stale Roles/Permissions is an annoying issue!!!
How does everyone get around the stale data from login.
I would go back to your initial approach of storing the claims inside the cookie.
If you do indeed have very long log in times then I would guard against stagnant claims by periodically refreshing the cookie.
If you are using forms authentication then you could intercept the FormsAuthentication_OnAuthenticate event in Global.asax, decrypt and manage the cookie (here), validate the user and cookie first then run a quick conditional check against a custom field in the userdata property, called refreshedDate.
If the last refresh date or creation date is greater than some configurable window then call to the database and refresh the claim data from the database. Finally update the refreshDate and claim data and update the cookie.
Update
Following on from your comment...
Just to say that it is not uncommon to hit the database for each request, that is to say I have known it happen in a number of production systems. Many people are probably using ASP.NET session state using MS-SQL database's. Typically I have seen it when there is a real security need to invalidate someone's session, deny access and log them out immediately.
If your database is on the network locally to your web servers and/or latency is acceptably low then it can be a perfectly workable solution. Just make sure your database queries are minimal and performance tuned to perfection, consider side steeping any ORM (if applicable) and use raw SQL connections to make things as fast a possible.
If database latency is high, the other middle ground solution is caching, using Redis or Memcached to house the results of your queries and invalidating the cache when permissions are altered etc... but obviously adding the required infrastructure and operational support for caching solutions is a serious consideration.
You can apply an expiration to the cookie; that way it dies and requires them to login. Or, keep their user ID in the cookie, but store their profile info in session. When session dies, the next time the profile is checked if it is null, make a query to the API again. This way, it's getting updated more frequently.
In addition to other suggestions, another option may be to use a notification mechanism from the underlying role/permission store whenever a user's data changes. This notification could then be used to invalidate the cached data on the web server. This would ensure that the cached data is returned in the majority cases but the store would then be hit only when the data had changed.
If the underlying datastore is SQL Serevr then consider something like SqlDependency.
This is obviously a more complex architecture but it would meet your requirement and only you could say whether it's worth the effort / complexity / tradeoff!

get session by ID

I'm currently working on Authentication and Membership system for my Web Application. It is licensed to number of users, that can be logged on in the same time.
So I come up with concept that I will make ActiveUsers table where I will store information about logged on users with their sessions' IDs.
Before new user can log in, application will check this table and will get all SIDs, then it will check whether particular session exists on server. If not it will delete record in table.
My question is: is there a way to check if session with particular ID exists on server?
Because HttpContext.Current.Session affects only current user.
There's a whole bunch of nifty events in Global.asax that you can probably use for deleting the row. Check out Session_OnEnd() for instance.
http://msdn.microsoft.com/en-us/library/ms178583.aspx
Edit: Just noticed that this really doesn't answer the question...

Storing UserData in memory

I'm fairly new to using Forms Authentication and am trying to wrap my head around how this all works. Basically, what I'd like to be able to do is store some user data that is associated with the FormsAuthentication ticket (data that comes back from my ldap server); however, I don't want to actually store this data in the cookie as it could be a rather large amount of data. Is it somehow possible to store this information in memory on the server, but keep it strongly tied to the ticket so that if the user times out or is logged out the data is destroyed as well. I realize I could use session variables to do this, but this seems awkward as I'd have to manually clean up the session variables if the user logs out. Is this possible or does this even make sense to do?
Why would you have to manually clean up a Session? The entire purpose of the Session dictionary is to allow you to do exactly what you want to do here: associate some known data with the user's current browser session. When the user's browser session ends for whatever reason, the HttpApplication and its Session are orphaned and GCed. So, I would just put your LDAP data into Session under a key, or set of same, and forget about it.

How to destroy a session of another than current user in asp.net

I'm using asp.net 4.0 with asp.net MVC 2.0 and the asp.net membership provider.
I need to terminate a the user session before I delete it. Otherwise if the user is still authenticated the next time it will visit a page null reference exceptions will occur when trying to access the user data and profile.
I get the Session.Abandon() method but what I'm looking for is the same on a user, something like user.AbandonSessions().
I realize this question has been asked before but I can't get a straight answer.
Thanks
I think you may be tilting at windmills. There are just too many things working against your desired goal.
If you adjust your perspective to embrace the arbitrary nature of a browser based app and instead of trying to eradicate all vestiges of a users state in order to avoid errors, rather take measures to ensure that the required data is present in the session and if not then recreate it or redirect the user to an appropriate location.
In any case, remember that in order to affect any session related action capably, you must force a request cycle to ensure the cookies are properly processed by the browser, but that is beside the point I am trying to make.
Good luck.
You could use a custom membership provider which instead of deleting an account, just deactivates that. You could also have the custom membership provider to lock the account at the same time.
FormsAuthentication.SignOut();
But you need to call it in the context of the user you want to sign out.

Resources