Logging out a user's other sessions in ASP.NET MVC3 with Forms Authentication - asp.net-mvc-3

I am building an ASP.NET MVC3 app using Forms Authentication and I'd like to log out all existing sessions for a user when that user logs in. I'm trying to prevent multiple people at different workstations from logging in and working under the same account.
Is there a standard way of handling this? Logging out the existing session is easy, but I haven't come across a way to check for other sessions by the same account and log them out.
I have a few ideas on how to hack this, but I'm curious if there's an established method for this using IIS or the FormsAuthentication API.

Because of the statelessness of the web, you can't "log out" a session until they make their next request (for instance, session might be maintained in a cookie, which can't be written on the client outside of the context of a request-response interaction).
There is still a solution, which assumes you are using session state, and preferably you have a common base controller for all of your controllers requiring "Authentication".
Upon successful login, generate a token (a guid perhaps) and store that with the session. Also write this to a application-wide store (database or application context for instance) keyed by the userid.
In the Base Controller (or otherwise you'd have to create an action filter) check the token in session against the token registered for the userid in the application-wide store. If they don't match, log out the user using the standard SignOut() call.

You could use the Membership.IsOnline property which is based on LastActivityDate:
A user is considered online if the
current date and time minus the
UserIsOnlineTimeWindow property value
is earlier than the LastActivityDate
for the user.

Related

Multi Tenant session management using multiple domains

I am trying to implement a feature similar to Slack where my application is a multi-tenant app, and a user can be logged into multiple accounts. Each account will be tied to a different domain. If logged into 2 different accounts, the user should be able to switch back and forth between the accounts. Also, the sessions should be managed independently. If one session expires, and the user needs to login, that expired session should not affect the other active sessions.
View Slack Image
The issue I am seeing is the different domain sessions override each other. This is a react frontend with Okta
Thanks for your time.
There are some gaps which require details, but here are few pointers that might help you.
Post authentication, you should be storing the authentication information like the session expiry, username in some form (local / session storage)
If I login to your application and choose a domain like (acme.com), the session information should be stored in a key like acme.com or hash(acme.com) so that how much ever domains, I login into, there will be unique keys to identify sessions and there will be no conflict of keys.
Once the domains are changed (like you switch workspaces in slack) there will be a new login session established (first time), which sets up the session information like described above.
For every workspace / domain change, the authentication libraries would be called and they would validate the stored session information, which gives the right data and expiry and user gets to use the application without issues.
Do share your implementation details or any issues had you implemented this solution.

Where to fill session after authenticating via WSFederationAuthenticationModule

We are using WSFederationAuthenticationModule in an ASP.NET MVC 5 application to authenticate users via Windows Azure ACS. We have tried multiple things to save some user specific data in the session after the authentication has succeeded but everytime we write to the session object we got the exception 'Session state is not available in this context'. Our favorite was the event System.IdentityModel.Services.FederatedAuthentication.WSFederationAuthenticationModule.SignedIn but of course at this time the session does not exist. Where is the recommended place to write initial data of an currently authenticated user into the session?
Have you considered using the ClaimsAuthenticationManager for this? The beauty of this is that you can access the current claims for the authenticated user (before your application code is executed), run whatever query you need to run, and then stuff new claims into the claimset of the principal. I've used this technique before for similar situations as you described.
If you really need to get access to the session data, then I think you want to look at the SessionSecurityTokenHandler class.

check for username against password in base controller mvc 3

I want to know how can I force a user to log in the the application again if the page is being opened in new tab or new browser.
Edit:-
My apologies I misunderstood the requirement.
I am authenticating the user in my log-in page but not anywhere else. So what is happening because of that, even if i log out of application and type url say bla.com/apple I can access my application.
I figured to prevent this from happening, I have to write a base controller that checks for the right user. Am I moving in the right direction.
Thanks
Addressing the edit -
Authentication can be handled per controller or on individual actions. Simple place the [Authorize] attribute appropriately. This assumes however that somewhere an authentication token is being set. [Authorize] checks against the HttpContext's current User (an IPrincipal).
You mentioned above that you're just validating against a local username and password, in one place, so I'm guessing that no token (session, cookie) are being set?
You have a few options here to get that token stored and persisted across requests:
ASP.Net integrated membership provider (Intro)
A custom MembershipProvider (Example)
Full-on custom flow. (Example)
Each has ups and downs and depends on how exactly you want to handle on-boarding your users. It's hard to answer more specifically because it can be a very large topic (and a very broad question).
Here's the official pages for MVC security.

Session identifier in Portal Application

I'm building several Portlets to deploy on a WebSphere Portal Server, and each Portlet is deployed in it's own WAR. Now, I'm needing to track every Portlet a user visits while it's logged on the Portal. I was trying to get the Session Identifier from a Portlet using this:
HttpServletRequest servletRequest = PortletUtils.getHttpServletRequest(request);
String sessionId = servletRequest.getSession().getId();
But after I logged in, I'm getting different sessionId values from every Portlet/WAR I visited. I guess that makes sense since there's one Session Scope per WAR.
So, how do I get an identifier for the Portal Session (not the Portlet one)? I'm seeing that JSESSIONID cookie is the same in every HTTP Request, but I'm not sure if that's exposed through Servlet or Portlet API.
Users that are not logged into the portal don't have a session like that. You can have Portal keep track of session information for anonymous users by enabling public sessions.
http://www-10.lotus.com/ldd/portalwiki.nsf/xpDocViewer.xsp?lookupName=IBM+WebSphere+Portal+7+Product+Documentation#action=openDocument&res_title=Portal_configuration_services_wp7&content=pdcontent
Look under navigator service for the property to change.
Also, I think this might be more easily accomplished in the theme or a portlet filter. You should still be able to get access to the Portal session in either of these places but you won't need to include code in every portlet.
Here's a link for creating a global portlet filter.
http://wpcertification.blogspot.com/2010/11/applying-global-filter-to-all-portlets.html
UPDATE: Like any big framework there are lots of options. I'll offer a brain dump of what I can think of / find. You may have to experiment and see which method you prefer.
The JSESSIONID cookie should be same for a user throughout the whole session. If the session expires they'll get a new JSESSIONID cookie. Using this you'll be able to track a user through a single session but possibly not across multiple sessions.
You could consider using getUserPrinipal() or getRemoteUser() off of the PortletRequest object. I haven't used those method in a while so you'll have to see what info comes out of them.
There is also request.getAttribute(PortletRequest.USER_INFO). You'll have to do some config in the portlet.xml to make certain attributes available in the Map that returns. There is an example here. We're using ibm-primaryEmail instead of the first and last name like the example on my current project.
Lastly you could look into using the PUMA API thats built into Portal. It'll will be a bit heavier on the coding and is obviously more container specific but should be able to do just about any job you need related to users.

How to store additional user info?

Here's the issue at hand: I have developed an ASP.NET MVC3 application using Razor. I have also implemented a custom membership provider and overridden the ValidateUser() method. Within, I query my db and get a lot of user information in addition to the password auth.
At the moment, I am pushing this information, i.e. companyId, to static properties of a class. This works and I can display/use this information throughout my app. The problem arises when a user closes their browser tab. Upon re-opening the app, the user is authenticated via a cookie, so they don't need to re-login; however, those static variables are blown away.
So guys and girls, how would/do you conquer this issue? Should I append the extra info to the session cookie? Or perhaps a better solution?
Use the ProfileProvider in ASP.NET.
For application level variables, they are going to be subject to application pool recycles and similar "simulated" restarts related to users starting all over. These variables should be completely independent of user usage and should be able to be recreated easily. If you have variables that are user dependent or that can't be restored easily without some sort of outside intervention then you will definitely need a different method of storage.
If the data is user specific, storing it in the session cookie is probably the best idea. If the data is user-related but branches multiple users it should be stored in a database or a flat file somewhere. If the data has nothing to do with users specifically then it should just be in a database or configuration file.

Resources