Access all ongoing ASP.NET Session States - asp.net

What we have is an ASP.NET web app that also does some signalR notifications. Since SignalR cannot access ASP.NET session states we need some other way to validate they are a client logged in on the web app.
In most situations you would think a static dictionary would help. As long as one of the ASP.NET Controllers made sure to keep a cache of key client info (via IP/browser info, or some generated token the client send up to signalR later) -- as long as this was done, then SignalR could validate the client connection before adding it to its pool.
However we are working in a server-farm situation, with SessionState backed by SQL. What this means is that a given server instance, even if it had a static cache of all its clients, may not know about Client C. Of course if Client C made a normal web request, it would find out about Client C when it fetched the SessionState. So the question is, IF work is handed over to a second server instance (Machine B) at just the right/wrong time, where Machine B does not know about client C (except via a context-dependent SessionState fetch, inaccessible from SignalR), HOW could we validate the client on the SignalR side?
All it would require is for some static means of getting ALL clients, OR, simply a "static" context for SessionState (i.e. a server-Session State). Because either way, we could sift through the individual client SessionStates and validate "yes, this client had a session state on a previous machine".
Is there any other way than for the client to reload the page, so that ASP.NEt can "cache up" its info locally? That is the only way I see so far.

I think it's a perfect scenario for "SignalR Backplane", it's designed for a webfarm situation to Scaleout SignalR. Lots of articles available, please search.

Related

SignalR Hub-2-Hub Communication with SQL Backplane in ASP.NET Owin

I have an ASP.NET Owin Web Api which is load balanced, which means there are multiple instances of it which don´t know each other. The web api hosts a SignalR hub with an SQL Server Backplane (for synchronising between instances), so clients can exchange messages regardless of which instance of the web api they are connected to. Everything working so far.
Client session data is stored in the db. The web api needs this info for processing requests for the client. Because it would be too slow to read the session data from the db for every client request, the web api is reading it only once (on first request from the client session) and caching it in-memory. This also works across multiple instances of the web api as every instance is holding it´s own session data cache.
But now the clients should be allowed to change for example the language, which results in an updated language in the session data stored in the db. The web api instance which processes the "change-language"-request of course can react to the changed session data and clear the session from it´s cache, which will lead to a reread of the session data from the db on the next client request. But the other web api instances don´t know about the session data change, their caches now hold outdated session data.
The web api instance which processes the "change-language"-request would somehow need to notify the other instances to drop their cache for session xyz. Unfortunately the instances don´t know each other, but all instances host SignalR hubs which are synchronised through the SingalR SQL server backplane.
Unfortunately a SignalR hub cannot directly send and receive messages. A HubConnection (client) is needed to do that. So the idea is when every web api instance is connecting to it´s own SignalR hub, it would be able to send messages to itself, which are then spread out to the other instances via the SQL server backplane synchronisation. But a HubConnection can only be established with an URL (http://host:port/signalr) but the web api instance doesn´t know it´s own base url.
So finally my question is:
Is there any way to establish a HubConnection to a hub running in the same process without providing an URL (I have access to the hub object)?
If not, is there any way for a SignalR hub to spread out messages and listen to messages through the backplane without a client (hub-2-hub communication)?
If not what else could I do to notify other instances of my load balanced web api and advice them to drop their session data cache?
Solved through distributed caching (IDistributedCache), as mentioned by Panagiotis Kanavos in the comments.

How does ASP.NET WebAPI using IIS store my users authentication state?

I have an asp.net Web Api 2 / Identity 2 application that requires a user to be authenticated. The authentication works but I notice that when I restart my local development machine and try to access a method that requires authentication then I get a failure.
As my application is unchanged from the asp.net sample then I think it uses cookies to store user data on the client. Where and how does the Server or IIS store information on which users have authenticated? Does it do this just the once or on every HTTP? Is there a difference between my using Token or cookie authentication in the way that the authentication and also authorization is checked on the server?
I think you are misunderstanding how authentication works with ASP.Net. As an example, let me show you some cookie details for a site of mine that uses Identity (note the token is actually in the cookie, the two are not mutually exclusive concepts):
Name __RequestVerificationToken
Value afeILhaIvRr56jXXXXXXXXXXX
Host site.azurewebsites.net
Path /
Expires At end of session
Note that the cookie, by default, expires at the end of your session. That means when you restart your development machine, your cookie is expired and your token is no longer valid.
In particular I have read that with token authentication then there is no need for continual re-authentication every time a request is made to the server
You need to understand that HTTP is a stateless protocol. Each request happens in a vacuum, and therefore you need to pass some data back to the server so that it can tell that the person who authenticated with Request A is really the initiator of Request B. Almost always, that piece of data is from a cookie. So, every request does indeed re-authenticate, and typically with a token in a cookie.
The only piece of data about your session that is stored on the client is the cookie (unless you are doing something atypical). The rest is on the server. How it is stored can vary:
Inproc: Easiest to setup, sessions are stored in process. So when your server or app pool is restarted, that data disappears
State Server Mode: Sessions are stored in process, but outside of the ASP.Net worker process, so the application can be restarted without losing session data
SQL Server: Unsurprisingly, this stores data in a database. Very resilient, but more work to setup. Also your best option if you are on a web farm.
ref: http://msdn.microsoft.com/en-us/library/vstudio/ms178586(v=vs.100).aspx
Expanding on the great answer by Chris, I would like to add that there are two possible models here. In forms authentication (which is the default membership type for asp.net) the cookie can either store authentication information and then it's called a ticket or the information can be stored in session, with the cookie being a simple identifier for "reconnecting" the authenticated session with the requesting client on each subsequent request.
This "reconnecting" happens in the Application_AuthenticateRequest method of the global.asax. If you are using the default forms authentication storage, i.e. an SQL DB created for you by the framework, the reconnection will be done automatically. If you are using a custom authentication store (like accessing active directory yourself or a custom users table structure) you can override the the method and reconnect the authenticated session using your own implementation. In any case, the authentication data is populated in the User.Identity object's different properties. From that point, if you use the [Authorize] attribute, the framework accesses the object to check if the user is indeed authenticated and authorized.
I any case, the authentication information is tied to both the cookie and the session. Assuming your session is InProc, like Chris said, when the session is lost (through timeout, app pool recycle or restart of the dev machine) the server-side of the session is lost and your authentication / session cookie is replaced by a new one on the next request.
EDIT: Ohh... and one more side comment. Make sure you distinguish between authentication and authorization. The client is not re-authenticated on each request. Authentication is the process of providing your credentials and being identified by the server. Authorization is, now that the server has verified who you are, on each request it checks if you are authorized to access the resource you are requesting.
The server doesn't store information about who's authenticated and who isn't. Depending on your authentication mechanism (forms, tokens?), typically, when a user logs in, the server will return some form of authentication token that the client should pass back to the server on each API call.
Without knowing more about your configuration, it's difficult to explain why when you restart your server you have to re-authenticate, it sounds like the authentication token generated by the server is invalidated on restart.
Where and how does the Server or IIS store information on which users have authenticated?
IIS does not store state based on cookie authentication. Everything is determined based on the request. Either a request has the correct encrypted information, or it doesn't. If you look at a default Forms authentication in ASP.NET, you will find a cookie called .ADUAUTH ... this cookie has all the information to authenticate the request. If the cookie is half expired, it will be reset, but that's all IIS does.
Does it do this just the once or on every HTTP?
Every HTTP request is unique, so yes, per HTTP request.
Is there a difference between my using Token or cookie authentication in the way that the authentication and also authorization is checked on the server?
It's always checked on the server: To find out more, check out: How ASP.NET Security Works: http://msdn.microsoft.com/en-us/library/ks310b8y.ASPX
I think my answer could be a little contradicting to all of the above.. But I think If I understand right..
IIS stores inside the memory space of the ASP.NET worker process, i.e the session data in the RAM.
The storing of authentication state depends on the authentication model you are using. For example: if you are using the Federated authentication, through ADFS, then when a user loads your web page he is required to sign in providing his credentials. The ADFS then sets the authentication token which is stored in the session data, the session id is stored as cookies in user's browser. The server has the mapping of Session Id to its session data.
Now the user is authenticated. The ADFS looks for authentication token to mark a user as authenticated.
When you restart the server, the session data is lost as the data is stored in RAM.
There are ways to handle this, there are 3 types of session storage:
1. InProc (Stored in memory space of ASP .NET Worker process - RAM)
2. State Server (Stored out side of ASP .NET worker process, like on cloud Azure storage)
3. SQL Server session storage (Stored in SQL server)
I think you are adopting 1, because of which you encounter the problem.
In cases 2 and 3, the session is not lost when you restart the server.
Several things --
Token based authentication is not really authentication. It is just issuing you a unique token (can be a guid, unique string, etc) and then associating it with something (like your IP address) and saving that association server side (in a database?). Now whenever you use that token, from the client app, the server checks the association already stored and serves or denies or request.
In many ways, it is very similar to using Cookies to maintain authentication. Only, token-auth was designed more for web services operation than for UIs.
In short: Out of the box, the membership provider will run it's authentication method and upon success, it will create an auth ticket/token/cookie that will be stored from the site. In addition to this, there is a session cookie that is stored with the site as well. When you make a page request, it'll pull these things and use them to determine whether or not you are already authenticated. If it finds the ticket and sees that it is still good, it'll allow access.
When you restart your local environment, the session and it's information is destroyed which is why you have to log in again.
There is an entire pipeline in the framework that makes all of this stuff happen (having to do with authentication, authorization, and identity) and there are number of ok articles on the interwebs explaining this, but imo, they're almost all incomplete or hard to follow. If you want a great soup-to-nuts explanation, PluralSight.com has some training videos that will deconstruct and explain the entire pipeline for you. Understanding the pipeline can help you implement your own custom authentication, and I highly recommend it.

Authenticate users syncing time out for 2 different sites

I have been puzzling over this and can't think of an good way of doing this. I am developing a website that would require the user to log in to use the system. I'm thinking of using ASP.NET MVC 4's built in authentication. That isn't much of a problem.
The user would be able to use tools on another server (our server would authenticate him and tell the other website, he is good to go, these messages are passed via HTTPS using XML). The other server, require us to create an authentication token for the user to use when the messages are passed between us.
We need to keep the token in our database to authenticate for every request/response with the other server. Which means that this "token table" knows nothing about the forms authentication time out on our server and vice-verse.
Now the problem, let's say the user uses the other server's tools. He would be on the other server for a long time, this would cause the authentication on our server to log him out, since there doesn't seem to be any perceived activity. The other server will not log him out since we are manually maintaining the token. This would be a troublesome for the user, because now, if he needs to use our service, he'll have to log in again even though he was "online" all the time.
Is there a way to "sync" the 2 authentications? At first I was thinking of getting our server to look up the "token table" (instead of using the built in authentication) so that if the last activity was x ago, the user will be required to log in again, this would solve the untimely logging out from our server. But I'm worried about the security implications.
What would be the best way to do this?
Thank you.
Desmond
If I've understood you correctly you are using Forms Authentication in an MVC4 application to authenticate users, but users will also use another web service located on a different server and so while they are using this other server you don't want the MVC4 application's authentication (for the user) to timeout. Is that correct?
If so, one idea that comes to mind is that your MVC4 application could have an API to the external world that would take in a username and use RenewTicketIfOld() to refresh the timer associated with the ticket. You could do this via the other web server making an HTTP request or by simply placing some AJAX on the page to call the API on every page.
There are, of course, security concerns with this method that you would need to consider. Without knowing more about your situation I'm not sure what solution would be best.

What are the possible threats while calling web services by using JQuery and how can avoid them?

I know this question can be too generic but for purposes of narrowing the question, here is a brief description:
I'm planning to forget about ASP.net UpdatePanel and move to use ajax via JQuery. I am afraid that because of the plain, client-side nature of JavaScript (and consequently JQuery code), any one looking to my web page's source can realize what is the URL of the web services I'm calling and also what are being passed to those web services.
When using UpdatePanel for these types of operations, I'm sure that calling web services is done on server-side and I have no concern regarding issues of information on calling sensitive web services being exposed publicly but now that I'm planning to use Ajax via JQuery, It worries me alot.
Are my concerns reasonable and if true, what are the best solutions for avoiding the threats of web-service-calling-info being exposed?
Clarification: when saying UpdatePanel, I mean utilizing a chain of techiques including ASP.net AJAX, code-behind and relying on server-side Dlls for performing async server-side operations instead of jquery Ajax which requires web services for intracting with server.
There is no way on the internet to protect your web services all the time by just hiding the URL. I am not sure when you say your updatepanel does the web service call from the server you are not taking the true power of AJAX.
One way to secure your web service is to use the authentication in the web service side. For example you need to send some authentication key every time you access the source, and this is very common, you have so many public web service who protects it self using auth key like OpenId implementation. In case you do not want to change the web service logic I think jquery way of AJAX is not a secure option.
Here's a thought, you can have two levels of web service, one which will open for all that you can use in the jquery. From the current web service, from the server side call the other secure web service. Even now you can configure your incoming request for some specific machine IP.
In this case other than your own server no body else can access to the web service securely kept behind the firewall. It is something similar we do while connecting to database server from application server.
Let me know if this helps.
I'm going to state the problems my answer is hoping to solve:
Assuming you host your services on a machine other than the web server, the problem is you give potential attackers the name/address of those machines.
Attackers can write scripts/bots to scrape your data.
Attackers can focus on your web services and try to hack them/gain access to your network.
Attackers can try to perform a DoS/DDoS on your web services.
The solution I've used in the past is to create a light weight proxy on the web server such that all AJAX calls simply point back to the current domain. Then when a call comes in, it is simply routed to the appropriate web service, which is hosted somewhere internally on the network.
It creates one additional hop on the network, but it also has these benefits:
It hides the actual IP of the machine hosting your services.
You can easily lock down that one web server and monitor unusual activity. If you see a spike in activity, you can potentially shut down the web services. (If you use a different machine, you'd have to monitor two boxes. Not a huge problem, but easier to monitor just one.)
You can easily put a distributed caching layer in the proxy. This protects you from load/denial of service (DoS) attacks and obviously supports normal web service traffic.
You can hide the authentication at the proxy level. The public calls won't betray your authentication scheme. Otherwise an attacker can see what tokens or keys or secrets or whatever that you use. Making a proxy on the web server hides that information. The data will still flow through, but again you can monitor it.
The real benefit in my opinion is that it reduces the surface area of your application which narrows what an attacker can do.
Since you refer to ASP.Net, know its viewstate can easily be decrypted. There's no failproof ways to protect your code (not to say urls called).
If you're web services are called with some parameters that could allow unrestricted and dangerous actions, then you'd better start using some users/roles/rights management.
If you're worried about "man in the middle" attacks, you best option is to use https.

Diving into ASP.NET Web API Authentication

I've been getting into the (relatively) new Web API that shipped with VS 2012 / MVC 4 / .NET 4.5, and have a custom message handler that handles authentication up and running. I also managed to hook it up to an old .NET 2.0 Membership Provider which was great.
I am now tackling the "authenticate with every HTTP request" issue by using a token in the HTTP request header, which I am comfortable with doing.
Now, for mobile apps when a user opens the app I show a login screen the first time, and don't show it again unless for any reason I get the "Unauthorized" message back. But for my web browser based projects I log in once and the browser (as long as it remains open) will remain authenticated.
What's the best way of forcing a time-out with this sort of authentication? I would prefer to log out based on inactivity, if anyone has done this. This one has me a bit stumped, so any guidance is appreciated :-)
Thanks!
There are two idle timeouts you need to consider.
Server Side idle timeout which expires to token you referred to
Client Side (mobile app) idle timeout which directs the user to re-enter credentials
For #1, You'd have to keep track of which tokens are active, or when they expire, etc... there are multiple ways to do this. How I'd recommend you implement it depends on if your deploying to IIS or Azure and if you'll be scaling out. In general though you want a central location where this information is stored. A DB works, but is relatively slow. Session State could work in Azure as the Session State can be shared across servers via App Fabric, but in IIS, you'd have to use an additinal component to share session state across the servers. Same holds true if you use the HttpRuntimeCache in .NET
It should also be noted that doing such checking server-side is critical so as to prevent someone from hijacking the token you refer to depending on how you ultimately decide to implement things.
For #2, What we did in our iOS app was keep track of the idle timeout. Each time user give input of any kind (e.g. BeginTouch event) in the app, we stop our idle timer and restart it. The timer is configure to take the user to the login screen should the timer fire. This same sort of thing should work well in Android, WP7, etc.

Resources