MVC 5 Keep User logged when browser is restarted - c#

First of all, I'm new to MVC, but I managed to create a simple custom login using Entity Framework, MVC 5 and C#. ( I do not want to use Identity because the idea is to get to know the functions behind it).
I'm currently doing this with Session Variables, so when the user exist in the DB, I store the info like Role, Name, etc. in Session Variables, but when the user closes the browser or I restart the app the session is lost so the user has to login again, how can I prevent that from happening and keep the user logged like Identity does?

There seems to be some confusion about how authentication and sessions actually work here.
First, sessions utilize cookies. That's how they work. A cookie is set with the session identifier so that the server can retrieve the appropriate session with each subsequent request. The only alternative is what's referred to as "cookie-less sessions", where the session identifier is passed around as a query string parameter. However, these are generally discouraged because inevitably the URL leaks and its far too easy to hijack user sessions this way.
Second, sessions on the server are not the same thing as a browser "session". The server-side session does not expire when you close your browser. That's just patently false. You can however, have the cookie containing the session identifier be set as a "session cookie", which causes the cookie itself to expire when the browser session ends. The server session still exists, only without the cookie, there's no way to look it up. However, you can just as easily have the cookie expire after a period of days or weeks. The fact that it's a cookie used to maintain a session doesn't necessitate that it be a "session cookie".
Third, there's different mechanisms of session storage. The default, because it requires no configuration, is what's called "in-proc". That means the session data is stored in memory by the web server process. When the web server process is terminated, its memory block is freed, along with your session data. Persistent sessions require persistent storage, meaning something like a database.
Long and short, there's nothing wrong with what you're doing, you just don't have your sessions configured properly. Refer to the MSDN docs on the <sessionState> Web.config element. You'll need to add something similar to:
<sessionState mode="SQLServer"
cookieless="false"
timeout="3600"
sqlConnectionString="[Connection String Here]" />

Related

lost session state in ASP.NET

I'm a beginner in ASP.NET and just a question on session state. I was reading a textbook which says:
the session state will be lost if the user closes and restarts the browser and the session actually remains in memory on the web server, because ASP.NET has no idea that the client has closed the browser or changed windows. The session will linger in memory, remaining inaccessible, until it eventually expires
I don't quite understand what does "remaining inaccessible" mean, because a cookie called "ASP.NET_SessionId" will be created for the first time when the session collection is used on client's machine, so even when the users close and then restart their browsers and access the page again, so the cookie contains session id will still get sent to the server, if the session still remains in memory on the web server, why it is inaccessible?
ASP.NET_SessionId cookie is created as "session cookie" (not "persistent" one - How do I create a persistent vs a non-persistent cookie?) and when browser closes completely (rarely happens now days) browser will drop all "session" cookies. Since value of the cookie is cryptographically secure random number there is no practical way to reconstruct the value of the cookie and hence retrieve value of old session from the server. Data associated with the value of the cookie will sit in server's memory (or SQL if you use SQL session state) but there will be no requests that can ask for it. Eventually the data will be cleaned when server side expiration happen (or server IIS process shuts down in case of in-memory session state).
Note that most modern browsers don't actually "close session" when you close all instances so you rarely see such case in practice. You can always "clear all cookies" to see it happening.

Where is the Session stored?

I ask to my friend, where is session stored? At Server or Browser?
He said, at the server.
Then I said "I think things saved at server called cache".
Then, I go to google search reading article, but I found no specific correct answer, at MSDN too, no specific answer.
Usually it is saved in the server's memory, but you can also have a database backed cache. It is never cached on the client, since it can contain information that shouldn't be available to the user, like the password to your database.
The full list of places where you can save the session state can be found on MSDN:
InProc mode, which stores session state in memory on the Web server. This is the default.
StateServer mode, which stores session state in a separate process called the ASP.NET state service. This ensures that session state is preserved if the Web application is restarted and also makes session state available to multiple Web servers in a Web farm.
SQLServer mode stores session state in a SQL Server database. This ensures that session state is preserved if the Web application is restarted and also makes session state available to multiple Web servers in a Web farm.
Custom mode, which enables you to specify a custom storage provider.
Off mode, which disables session state.
Session itself is stored on the server side.Each browser accessing the server will get from the server unique Session ID. This Session ID browser sends to each page requested to the same server.
Session
So on client (browser) side, only Session ID is stored in the browser cookie.
(this is default behavior, when session cookies are enabled in the browser settings... there is also a technique called "URL rewriting" to embed Session ID as URL query parameter, each time the server is called, enabling the application to work even if browser session cookies are disabled)
For more information go through this http://ejvyas.blogspot.in/2010/02/where-is-stored-is-it-in-browser-or-at.html
Quick answer: on both sides.
Previously, the session was stored on a server side. This approach implies that you have to go to a server side each time you create or validate session. The session also have to be replicated for all the web-servers. These things can sufficiently harm the performance.
The another one oldschool way to store the session data as a cookie (as it is mentioned in answers). The obvious flow is that cookies has 4kb limit.
In order to overcome it, the World Wide Web Consortium defined the client side sessionStorage, that can be instantly added or validated and does not demand to replicate the data between web-servers.
It can be seen in browser's Dev Tools / Application tab. For example, this is how the session for my Facebook page looks like:

How do I recover a Session based on the SessionID?

Context is:
I need to send the SessionID (will be encripted) to an app, then the app saves the session ID and on the next query the app sends me back the SessionID so I can use the stored Session variables.
So HttpContext.Current.Session.SessionID gives me the current SessionID.
But... how do I recover the Session based on the SessionID?
P.S. I am aware that this is a duplicate of this unanswered question: How do I get a session by SessionID in C# so as a plus if there is no way of retrieving the Session from the SessionID I would ask if there is another way to achieve that.
As far as I am aware, there is no public API available to load a session based on session ID (I have asked the question here, as well). You can hack it using reflection, but that will only work if your site is in a full trust environment and you are okay with the performance implications of using reflection.
As was pointed out in the comments, session state is normally driven by a cookie (by default named "ASP.NET_SessionId"). If you pass the cookie from the request of your "app" (which I am assuming you mean a remote application) to the server, you can then access session state simply by calling HttpContext.Current.Session on the server side. You just need to add the cookie to the headers of the request from the application for it to work.
However, I don't think session state is the persistence mechanism you are after for your scenario. Rather than dealing with cookies, it would make more sense to store your state in a persistent format such as a file or a database and use a GUID or other unique identifier to access it based on an ID passed in through the URL.
As Alexi pointed out, another possibility would be to build your own session state provider that you put your own back door into in order to access the raw data, but it will take quite a bit of work to pull that off.

Server session handle in multiple browsers in asp.net?

My asp.net session objects are storing in SQL server.I am storing an ID in session. If client open another browser and storing different ID in session. I need to notify client is “are you sure you want both ID’s open?” in same based user logged user.
Application runs on logged in user (not anonymous)
How can we check this in asp.net?
Session is not linked to an authenticated user, and there is no way of accessing an other connection's Session without knowing its SessionID.
Usually this kind of problem can be solved using cache instead of session state. With cache you can create your own user-based keys to store data. Depending on whether you are planning to just run your web app on one server or in a web farm environment, you can either use asp.net in-process cache or one of numerous distributed cache solutions (like memcached which I'm using in my web projects with great success).
There are a couple ways to go about this:
Option #1, in your user table, add a value called "session id"
When a user logs in, check to see what their last session id was. Then test to see if it's still a valid session. If it is, ask them what they want to do. Store the latest session id in that table after each log in.
However, I'd go with option #2: Don't do this. If the user wants to open multiple browser windows to access your application then let them. There's probably a pretty good reason for it. Most (as in nearly all) users have no idea what "session state" even means and they really have no desire to know. All they care about is getting their job done.

global admin page for multiple applications in ASP.Net

I was wondering if anybody could give advice on a secure way to implement a global login. I have an admin page that accesses active directory admin groups after typing in your username and password.
current logged in account (on computer) does not matter
user in web browser goes to web app, redirects to global login page with query string of app name
types user name and password of an account in AD (not necessarily current computers logged in user)
authenticates (looks up user, pass etc and authentication is valid)
redirects back to original web app.
Once redirection happens, how do I securely tell the original web app that this user is ok until the original web session dies?
The way I'm thinking of implementing it:
My original thought was to pass the session ID of original app to the login page as well as the app
name. Store that session in a DB once authentication is checked. Master page of the other app validates on page load that the session ID matches. On session close, remove current session ID from DB.
You cannot depend on sessionID accurately in some cases. SessionID only becomes a constant value after a (any) page makes a request for a session variable, if you dont have Session_Start not defined in global.asax. If you log the user in and the default page does not access session, you will end up with a different session id for the subsequent requests until a request to session is made. Usually it is always constant as there is a default empty session_start event in global.asax.
But similar to your model, you could generate a GUID (or make sure you access session on login/authentication) and store it in the user table with an expiration. Your web sites can check this key and if currently valid, auto sign the user in.
You also cannot depend on session_end event since there is no real accurate way of detecting it (eg: user closing browser). So, you should store this ID with an expiration time along with it, preferably the same as session timeout. Just like session, you will need to extend this, something like a sliding expiration. This way, this id will be expired after a period of inactivity.
also, this Claims-Based Single Sign-On for the Web may be of interest to you.
What you're describing sounds like it would be better implemented using Windows Identity Foundation and Active Directory Federation Services 2.0. I don't know the extent of all your requirements, but it might be valuable to check out what these will give you out of the box.
You could use a cookie. If you pass the name of the application to the login page, you can set that application name to the PATH property of the formsauthentication cookie. By setting the PATH property, you're effectively limiting the readability of the cookie to the pages within that path. Because it's a common login interface, this may require some code being done perhaps in a common page base class that handles the parsing of the cookie information.
You can share authentication tokens between .NET applications, even between .NET CLR's if you want to. I think this will give you the single sign on you're looking for.
At a high level you need to share a machine key between the applications. You can generate the machine key using the key generator app code example found on this link, and providing you then reference the same key in each application the sign on can be shared:
http://msdn.microsoft.com/en-us/library/ms998288.aspx
There are some consideration when looking at things across domains or accross machines/web farms etc, but if all apps are on the same box it's not too hard.
The harder side of things is sharing things like session state which I don't believe can be done accross app pools. (I ended up recreating the session object on the new app manually last time I did it :( but that was between 1.1 and 2.0 apps )
EDIT: I did a rough write up of it last year and was using it as a test for a demo article on my site, might be worth a read through if you want things broken down a bit more (Ignore the unfinished site!):
http://www.dougmcdonald.co.uk/test/html5/v5/articles/2010/05/10/Sharing-forms-authentication-between-applications/

Categories