clear session on every first visit - c#

I have a facebook application which is session based. i am having bad behaviour as follows: if the user is using the app then logs out from facebook and some other user logs in to facebook and logs in the app they see the user data who just logged out.
Essentially I d like to clear the session every time visitor hits the first page.
I have a HomeController which extends BaseController in base controller i check if the user has a session.
where should i put Session.clear() in order to prevent user to access old user session?
on
HomeController{
[authorize for facebook]
indexAction{
redirect to home action
}
}
my concern is that when indexaction is invoked Before that base controller will be invoked and i will get a infinite loop.
Note: I m using a UserCookie which i store the user id and expiration of the cookie within.
any ideas?

It looks like you want to check if Facebook user ID matches data in session state. The easiest would be to put something like Session["FBID"]=facebookId and than check on every request if current facebookId matches `Session["FBID"], if not - clear session (irrespective of current location).

Related

c# mvc: RedirectToAction() and browser navigation buttons

In my application, i am storing an object into session which is passed to a web service to return data to display in a table. If the session exists, then it will not ask the user to input fresh data. However, if a user selects a link called "New List", then the session data will be cleared and the user prompted to enter new data.
In my code, i have an anchor defined like so:
New List
Which will trigger this Controller Action:
public ActionResult NewList()
{
Session["new_list"] = "y";
return RedirectToAction("List");
}
And then continue to execute this action:
public ActionResult List()
{
if ((string)Session["new_list"] == "y")
{
//clear session variables, load fresh data from API
}else{
//display blank table. Ask user to input data to retrieve a list
}
....
}
Now, the issue i have is when a user navigates away from the list page, and then navigates back with the browser's back button, it is still calling newlist. In the history of the browser, instead of storing List it is storing newlist which is causing the session variable to clear. What can i do to stop this from happening or is there a different mechanism to use in c# mvc that can help me achieve the desired effect.
Your main problem here is that the NewList action uses GET when it should really be a POST.
A GET request is never supposed to alter the state of a resource, but simply return the current state of the resource; while a POST request allows for the altering of a resource.
Because you allow the NewList action to be called with a GET request, the user's browser assumes (quite rightly on its part) that nothing bad/undesired will happen if it simply repeats the request in the future, e.g. when a user uses the back button.
If instead a POST request is issued, a user browser will never re-issue the request without the user confirming they actually intended to re-issue it.
The solution to your problem then is modify this to the standard PRG pattern: POST/Redirect/GET; that is, send a POST request to perform the state change, redirect the user browser to another page, and GET the result page. In this scheme, pressing the back-button would effectively "skip" over the state change action and go the previous page the user was on.
To accomplish this in MVC:
[HttpPost]
public ActionResult NewList()
{
//clear session variables, load fresh data from API
return RedirectToAction("List");
}
public ActionResult List()
{
// whatever needs to happen to display the state
}
This does mean that you can't provide the "New List" action directly as a hyperlink in the page, as these will always issue GET requests. You will need to use a minimal form like so: <form method="post" action="#Url.Action("NewList", "Alert")"><button type="submit">New List</button></form>. You can style the button to look like a normal hyperlink as desired.
The reason it storing NewList is because you are redirecting to "Alert/NewList", and its the string in your URL for making hit to "NewList" Action, So whenever you are try back button the browser gets this "Alert/NewList" URL, hence its making hit to action "NewList".
But now, I am not getting why the session gets clear. because you are initializing the session in "NewList" itself. Still i suggest you to use local-storage to assign values with session.

MVC logout all active sessions after same user login

I have c# mvc web application.There is simple login page according to email and password. Now I have a need like that:
When a user login to the system, all active sessions that same email address will logout.
How can I achieve this?
You can use Session.Abandon() or Clear() to abandon the current session, but if there are multiple people logged in with the same address, this will not address that.
You'd have to build that detection in; for instance, you could update a flag on the table that represents your users and then in the other user's sessions periodically check the table if they were re-logged in. OR when a user logs in, create a token in a database table with an expiration date; associate that token to a user in a cookie. When logged out or logging back in, you could invalidate the token associated to that email address, and each user, when they attempt to access the application, could be rejected by your application checking whether the token is expired.
The Abandon method should work (MSDN):
Session.Abandon();
If you want to remove a specific item from the session use (MSDN):
Session.Remove("YourItem");
If you just want to clear a value you can do:
Session["YourItem"] = null;
If you want to clear all keys do:
Session.Clear();
If none of these are working for you then something fishy is going on. I would check to see where you are assigning the value and verify that it is not getting reassigned after you clear the value.
Simple check do:
Session["YourKey"] = "Test"; // creates the key
Session.Remove("YourKey"); // removes the key
bool gone = (Session["YourKey"] == null); // tests that the remove worked

Registering a new user overwrites current user session - why?

I've come across an issue when registering new users with my app. The behaviour looks to be by design, but I don't understand why.
My problem is as follows (and I know it's a bit of an edge case):
User browses to my site's login page in two separate tabs in the same browser.
In the first tab, the user logs in and is correctly redirected to my home page.
In the second tab, the user follows my signup logic (which doesn't require any kind of page refresh, it's all done with client side code that culminates in a jQuery AJAX POST to the built in ServiceStack RegistrationService's /register endpoint)
Instead of creating a new user, the second user's details overwrite that of the logged in user's UserAuth record, and the first user can no longer log in.
Looking at the code in ServiceStack.ServiceInterface.Auth.RegistrationService, this behaviour appears to be 100% intentional:
var session = this.GetSession();
var newUserAuth = ToUserAuth(request);
var existingUser = UserAuthRepo.GetUserAuth(session, null);
var registerNewUser = existingUser == null;
var user = registerNewUser
? this.UserAuthRepo.CreateUserAuth(newUserAuth, request.Password)
: this.UserAuthRepo.UpdateUserAuth(existingUser, newUserAuth, request.Password);
Once the first user is logged in, the session cookie for that user gets sent with the registration request, causing the existingUser variable in the code above to be populated with the UserAuth for that user, which is then updated with the registering user details.
Can anyone explain why the code's been written in this way? And is there any way around it without replacing the RegistrationService with my own implementation?
This is the feature that lets you to auto-merge different Auth Providers into the same account in ServiceStack.

Set proxy user in a GenericPrincipal, while keeping the old identity, using MVC

I have a site where I allow some users to proxy in as an other user. When they do, they should see the entire site as if they where the user they proxy in as. I do this by changing the current user object
internal static void SetProxyUser(int userID)
{
HttpContext.Current.User = GetGenericPrincipal(userID);
}
This code works fine for me.
On the site, to proxy in, the user selects a value in a dropdown that I render in my _layout file as such, so that it appears on all pages.
#Html.Action("SetProxyUsers", "Home")
The SetProxyUsers view looks like this:
#using (#Html.BeginForm("SetProxyUsers", "Home")) {
#Html.DropDownList("ddlProxyUser", (SelectList)ViewBag.ProxyUsers_SelectList, new { onchange = "this.form.submit();" })
}
The controller actions for this looks like this
[HttpGet]
public ActionResult SetProxyUsers()
{
ViewBag.ProxyUsers_SelectList = GetAvailableProxyUsers(originalUserID);
return PartialView();
}
[HttpPost]
public ActionResult SetProxyUsers(FormCollection formCollection)
{
int id = int.Parse(formCollection["ddlProxyUser"]);
RolesHelper.SetProxyUser(id);
ViewBag.ProxyUsers_SelectList = GetAvailableProxyUsers(originalUserID);
return Redirect(Request.UrlReferrer.ToString());
}
All this works (except for the originalUserID variable, which I put in here to symbolize what I want done next.
My problem is that the values in the dropdown list are based on the logged in user. So, when I change user using the proxy, I also change the values in the proxy dropdown list (to either disappear if the "new" user isn't allowed to proxy, or to show the "new" user's list of available proxy users).
I need to have this selectlist stay unchanged. How do I go about storing the id of the original user? I could store it in a session variable, but I don't want to mess with potential time out issues, so that's a last resort.
Please help, and let me know if there is anything unclear with the question.
Update
I didn't realize that the HttpContext is set for each post. I haven't really worked with this kind of stuff before and for some reason assumed I was setting the values for the entire session (stupid, I know). However, I'm using windows authentication. How can I change the user on a more permanent basis (as long as the browser is open)? I assume I can't use FormAuthentication cookies since I'm using windows as my authentication mode, right?
Instead of faking the authentication, why not make it real? On a site that I work on we let admins impersonate other users by setting the authentication cookie for the user to be impersonated. Then the original user id is stored in session so if they ever log out from the impersonated users account, they are actually automatically logged back in to their original account.
Edit:
Here's a code sample of how I do impersonation:
[Authorize] //I use a custom authorize attribute; just make sure this is secured to only certain users.
public ActionResult Impersonate(string email) {
var user = YourMembershipProvider.GetUser(email);
if (user != null) {
//Store the currently logged in username in session so they can be logged back in if they log out from impersonating the user.
UserService.SetImpersonateCache(WebsiteUser.Email, user.Email);
FormsAuthentication.SetAuthCookie(user.Email, false);
}
return new RedirectResult("~/");
}
Simple as that! It's been working great. The only tricky piece is storing the session data (which certainly isn't required, it was just a nice feature to offer to my users so they wouldn't have to log back in as themselves all the time). The session key that I am using is:
string.Format("Impersonation.{0}", username)
Where username is the name of the user being impersonated (the value for that session key is the username of the original/admin user). This is important because then when the log out occurs I can say, "Hey, are there any impersonation keys for you? Because if so, I am going to log you in as that user stored in session. If not, I'll just log you out".
Here's an example of the LogOff method:
[Authorize]
public ActionResult LogOff() {
//Get from session the name of the original user that was logged in and started impersonating the current user.
var originalLoggedInUser = UserService.GetImpersonateCache(WebsiteUser.Email);
if (string.IsNullOrEmpty(originalLoggedInUser)) {
FormsAuthentication.SignOut();
} else {
FormsAuthentication.SetAuthCookie(originalLoggedInUser, false);
}
return RedirectToAction("Index", "Home");
}
I used the mvc example in the comments on this article http://www.codeproject.com/Articles/43724/ASP-NET-Forms-authentication-user-impersonation to
It uses FormsAuthentication.SetAuthCookie() to just change the current authorized cookie and also store the impersonated user identity in a cookie. This way it can easily re-authenticate you back to your original user.
I got it working very quickly. Use it to allow admin to login as anyone else.

How can I set up ASP.NET login to allow the UserName or UserId to be retrieved later on in the session?

I'm trying to create a login system for my website, I've created a custom login.ascx and when the user clicks [ Login ] a div pops up with the contents of login.ascx.
Then after the user enters their credentials, they click on the Login button. They get validated and logged in using this code in the login click function:
if( Membership.ValidateUser( userName.Text, password.Text ) )
{
//Here is where I'm not sure what to do
}
else
{
LoginError.Visible = true;
}
So in the section where I'm not sure what to do, I would like the user to get logged in (Not sure if that means creating an authentication ticket or whatnot). What does is the next step to actually log the user in, I don't want them to get redirected anywhere since they are on the correct page already.
I would also like to be able to retrieve their user name or user id later on for use in my web services. So, for this should I do a Session.Add to create a new session value or is there some other way of storing the data that is preferred?
For authenticating the user,
FormsAuthenatication.SetAuthCookie(username, false/*true if you want to remember the user's login*/);
This logs the user in. You can later use
Page.User.Identity.Name
to retrieve username of the current user and
Page.User.Identity.IsAuthenticated
to check if the user is logged in.
There's no need to store it in Session. Just use:
FormsAuthentication.SetAuthCookie
to send an authentication ticket to the client. Then use HttpContext.Current.User.Identity to retrieve it later.
I find using the membership provider is useful, I would recommend it
Scott Guthrie posted great blog on this
http://weblogs.asp.net/scottgu/archive/2006/05/07/ASP.NET-2.0-Membership-and-Roles-Tutorial-Series.aspx

Categories