Session Log Out Issue - asp.net

There is web application which is created on asp.net.
This application works perfectly when i run this on my local.
I have used session to store the userId of the user in the session.
In every page where i want only logged in user to be able to enter i have written code like.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Session["userID"] == null)
{
Response.Redirect("login.aspx");
}
}
}
So when session does not have userID user gets automatically redirected to login page.
I am facing two problems
1.When I deploy it to BigRock shared server.User automatically gets logged out in 5 minutes.It is defined session time out set in that server which I can not change. I do not want my user to get logged out automatically.
2.Payment Gateway is also integrated with this website and when the user clicks on check out .He gets redirected to payment gateway but when after entering his payment details and transaction completes when he gets back to response page ,he again automatically gets logged out whether 5 minutes was completed or not.This also works fine when I test this for the condition when I run this website on my local.
Every help is appreciated.Thank You So much in advanced!
Please let me know if you need any more clarification or source code.

Well, you can always try logging back the user based on the order-id received from PG. Since the response from PG is usually protected by checksum, you can rely on it's authenticity to carry back the user to your page. Just update your login session by using FormsAuthentication.SetAuthCookie method to re-login the user.
In your case since your directly assigning userdId to Session (IMHO, not the best way to manage logins though. Try searching for MembershipProvider), the steps are pretty straight forward.
Get the OrderId from PG response.
Fetch the associated userId from Orders table (For this you must have associated each user with their orders.
Save the userId in Session.
Redirect the user to secure page.
Why are we not asking for password? Because, responses from PG are usually protected by means of hashing and usually immune to tampering. So you can safely bet on the authenticity of the user redirected by PG.

Related

Single login in asp.net

I am working on a website for a college project. I want to add a feature to my project website.
When a user logs in to the website, all other logins for the same user account should be logged-out, i.e., only one login per account should be allowed at a time .
When the same user ID is trying to log in on multiple devices, how do I kill the session on the other device?
You can be out of the situation by doing something like this:
The Idea
Whenever a user logs in to their account we store their username along with their Session ID. The next time someone that is logged in tries to make a request, we check if their Session ID matches with the Session ID we stored for them. If it's a mismatch, that means someone else logged in after them! Thus we can safely log them out.
The Implementation
We'll make use of 3 things.
Session ID: Allowing us to distinguish someone's browsing instance
Global.asax: To grab the Session End Event
One Storage Location:
HttpContext.Current.Application
Database
If your website is running on one server, then you can just use Application, but if its running on multiple you'll have to go for the Database. The code shows it being done for Application.
When the user logs in you need to store the session id:
UserAccout ua = GetUserAccount();
HttpContext.Current.Application["usr_" + ua.UserName] = HttpContext.Current.Session.SessionID;
And when they log out we need to clear it:
UserAccout ua = GetUserAccount();
HttpContext.Current.Application.Remove("usr_" + ua.UserName);
In your Global.asax file you should call the same Logout code to clean up when their Session Ends
void Session_End(object sender, EventArgs e)
{
UserAccout ua = GetUserAccount();
if (ua != null)
{
HttpContext.Current.Application.Remove("usr_" + ua.UserName);
}
}
And now that we need to actually check if a user should be kicked out or not, so execute this in the beginning of all requests:
UserAccout ua = GetUserAccount();
if (!HttpContext.Current.Application["usr_" + ua.UserName].Equals(HttpContext.Current.Session.SessionID))
{
Logout();
HttpContext.Current.Response.Redirect("SignOut.aspx");
}

programmatically logout a "specific" user

Is it possible in Asp.NET MVC to proframmatically logout a user? I am aware that you can use:
FormsService.SignOut();
But this refers to the context of the webpage making the request. I'm trying to prevent a user logging in twice. So if I call:
MembershipUser membershipUser = Membership.GetUser(userName);
if (membershipUser.IsOnline == true)
{
// log this user out so we can log them in again
FormsService.SignOut();
}
Calling FormsService.SignOut(); has no bearing on the context of the user say, with another webbrowser who is logged in already?
One common method to accomplish this goal is to, on each page load, check whether the current user needs to be signed out.
if (User.Identity.IsAuthenticated && UserNeedsToSignOut())
{
FormsAuthentication.SignOut(); // kill the authentication cookie:
Response.Redirect("~/default.aspx"); // make sure you redirect in order for the cookie to not be sent on subsequent request
}
You may be concerned that this method will be too slow,
"Why do I have to call this damned function each page load? It probably hits the database each time!"
It doesn't need to be slow. You may cache a list of users that should not be signed in at any given time. If their username is in that cache, then the sign out code will be triggered next time they access a page.
Take a look at this blog How to allow only one user per account in ASP.Net

Store cookie for other site

I have multiple asp.net sites. When a user logs unto one of the sites, I want to store a cookie telling me that a user has logged on. When the user later visits one of the other sites I have, I would like to read the cookie from that site.
AFAIK you neither can read cookies from or write cookies to other sites, so what could a workaround be?
Perhaps making a redirect to http://www.othersite.com/SaveCookie.aspx ?
Give me some ideas :-)
One of our clients has exactly the same requirement (logging into multiple sites on different domains), complicated by the fact that one of the sites requires that the user is logged in to a classic ASP application, a .NET 1.1 application and a .NET 3.5 application running on different hardware, but under the same domain...
We've basically implemented a system of round-robin style redirects, where each domain logs the user in, then bounces them on to the next domain until they return to the original domain at which point they are redirected to their original request.
So (pages and domains changed to protect the innocent):
User requests www.example1.com/page1.aspx
A cookie is set that tells us the user was attempting to access page1.aspx, and the user is sent to the www.example1.com/login.aspx
The user logs in, and is then redirected to www.example2.com/processlogin.aspx?token=EncryptedToken
ProcessLogin.aspx checks for a cookie telling it where to direct the user, if it can't find one, it decrypts the token, logs the user in on example2.com, and then redirects them to www.example1.com/processlogin.aspx?token=EncryptedToken (or example3.com - repeat as required)
As in 4, ProcessLogin.aspx checks for the cookie, finds it, deletes it and redirects the user to /page1.aspx.
If the user later on visits a page on www.example2.com, before the authentication ticket timeout, they will still be logged in on that site as well.
Edit to respond to comment
That depends on how you are making the "request to the other pages". If you make the request from your code behind, what you're doing is effectively setting the cookie on the server, rather than on the users browser.
Cookies need to be issued by the server to the client browser, and that is done in the headers of the page response - so you need to direct the users browser to a page on the other site to issue the cookie from that domain.
You could generate a request to the other page in an IFrame, or try and do it in a self closing pop-up window - but that has other issues like pop-up blockers, flickering windows, etc.
After some investigation we found that a round-robin set of redirects like this was the simplest and most reliable solution.
A very basic code setup:
An .aspx page, containing a Login control, with a method "OnLoggedIn" attached to the LoggedIn event of the control:
void OnLoggedIn(object sender, EventArgs e){
string returnUrl = Request.QueryString["returnUrl"];
// Create new cookie, store value, and add to cookie collection
HttpCookie myCookie = new HttpCookie("WhereTo");
myCookie["ReturnUrl"] = ReturnUrl;
Response.Cookies.Add(myCookie);
// Redirect user to roundtrip login processor on next domain.
// Work out domain as required.
string redirect = GetNextDomain();
// Add encoded user token
redirect += "?token=" + EncodeUserToken();
// Redirect the user, and end further processing on this thread
Response.Redirect(redirect, true);
}
Then on both servers you have ProcessLogin.aspx, that has something like this in it:
protected void Page_Load(object sender, EventArgs e){
// Look for redirect cookie
if (Request.Cookies["WhereTo"]["ReturnUrl"] != null){
// Save value from cookie
string redirect = Request.Cookies["WhereTo"]["ReturnUrl"];
// Delete original cookie by creating an empty one, and setting it
// to expire yesterday, and add it to the response.
HttpCookie myCookie = new HttpCookie("WhereTo");
myCookie.Expires = DateTime.Now.AddDays(-1d);
Response.Cookies.Add(myCookie);
// Redirect the user, and stop processing
Response.Redirect(redirect, true);
}
// Still here, so log in and redirect
string encryptedToken = Request.QueryString["token"];
if (!string.IsNullOrEmpty(encryptedToken)){
// Decrypt token, and log user in
// This will vary depending on your authentication mechanism
PerformLogin(encryptedToken);
}
// Redirect user to roundtrip login processor on next domain.
// Work out domain as required.
string redirect = GetNextDomain();
// Add encoded user token - no need to recalculate, it will be the same
redirect += "?token=" + encryptedToken;
// Redirect the user, and end further processing on this thread
Response.Redirect(redirect, true);
}
You're looking for a Single Sign-On (SSO) solution.
If it's possible for you to host your sites at different subdomains below the same domain, you can save cookies that are shared for the whole domain, e.g.:
"site1.yourdomain.com" and
"site2.yourdomain.com"
can both read cookies saved to the domain "yourdomain.com"
Another alternative is to tell the other site about the login via a request to it, as in your redirect suggestion. You could do this in several ways, e.g. by loading the page in an iframe, sending the data directly from one server to another, and so on. None of these are particularly elegant, though, and in the case of login, as Tomas Lycken says, you should really be going for a proper SSO implementation.

Restricting log in for each user to a single computer in ASP.NET

Looking for a robust and efficient implementation where I can restrict a user to only log in to my web app from a single computer.
If a the same user is already logged in and another person tries to log in from another computer then I should either have the option to
end the session of the currently logged in user, or
show a message to the new person trying to log in with the same user account.
Currently authentication is done using Forms Authentication with custom membership and role providers.
Our server is showing it's age so I'm looking for something that uses the least processing power and hopefully does very few db reads (if at all needed). My initial naive implementation is to store the IP (in db? app state?) on a successful login and then check on each page request or each other log in attempt depending on scenario. Would like to hear of better ideas =)
You can do it this way:
Store the current Session Id (HttpContext.Current.Session.SessionID) in the Application object, along with a time stamp.
At the next request (e.g. in Global.asax), check if the current session is the same as before and if less than 20 minutes have passed. If the session is the same, let them work normally. If they are different, only let them work if 20 minutes have passed. Do update the Application object.
This will allow one user at a time, on one computer at a time. It is probably not 100% safe, but it is a very viable way to do it.
Earlier i got a similar situation, and followed the below appraoch
Along with login name maintain a session id and timestamp in each request.
And allow the user to gain access only if both login & session id combination are same.
If the combination differs,you can either
log off the first logged in user (by
showing notification to them
saying the some other user logged into your
account ) 0r
log off the newly enterd user saying already this
account is in use
you can use timestamp of the request to validate the session timeouts..
Hi
It's the way I've implemented this (I've added these lines to onload of my Page's base class):
bool authenticated = UserIsAuthenticated();
if (Session["~~~loginprocessed"] == null)
{
if (authenticated)
{
// user just logged in:
if (Application[Page.User.Identity.Name] != null)
Application.Remove(Page.User.Identity.Name);
Application.Add(Page.User.Identity.Name, Session.SessionID);
Session.Add("~~~loginprocessed", true);
}
}
else
{
if (!authenticated)
{
Session.Remove("~~~loginprocessed");
}
}
if (authenticated)
{
if ((Application[Page.User.Identity.Name] == null) || (Application[Page.User.Identity.Name].ToString() != Session.SessionID))
{
System.Web.Security.FormsAuthentication.SignOut();
// show some message to user which will tell he has signed out because of login from somewhere else!
}
}
If I understand your question correctly, you wish to make sure each user can only be logged on once at a given time. As far as I know the ASP.NET Membership provider only stores the last activity date and the last login date. You could keep a list of user id's that are logged in and display your message when a new user tries to login as a user that is already in that list. A complication would be that you need to remove the user from this 'LoggedOn' list when he logs out. You can perhaps use session_end in Global.asax

Avoid losing PostBack user input after Auth Session has timed out in ASP.NET

I have a form that sits behind ASP.NET forms authentication. So far, the implementation follows a typical "out of the box" type configuration.
One page allows users to post messages. If the user sits on that page for a long time to compose the message, it may run past the auth session expiration. In that case, the post does not get recorded... they are just redirected to the login page.
What approach should I take to prevent the frustrating event of a long message being lost?
Obviously I could just make the auth session really long, but there are other factors in the system which discourage that approach. Is there a way I could make an exception for this particular page so that it will never redirect to the Login so long as its a postback?
My coworker came up with a general solution to this kind of problem using an HttpModule.
Keep in mind he decided to to handle his own authentication in this particular application.
Here goes:
He created an HttpModule that detected when a user was no longer logged in. If the user was no longer logged in he took the ViewState of that page along with all the form variables and stored it into a collection. After that the user gets redirected to the login page with the form variables of the previous page and the ViewState information encoded in a hidden field.
After the user successfully reauthenticates, there is a check for the hidden field. If that hidden field is available, a HTML form is populated with the old post's form variables and viewstate. Javascript was then used auto submit this form to the server.
See this related question, where the answers are all pretty much themes on the same concept of keeping values around after login:
Login page POSTS username, password, and previous POST variables to referring page. Referring page logs in user and performs action.
Login page writes out the form variables and Javascript submits to the referring page after successful login
AJAX login
If you don't care if they're logged in or not when they POST (seems a little iffy security-wise to me...) then hooking HttpContext.PostAuthenticateRequest in an IHttpModule would give you a chance to relogin using FormsAuthentication.SetAuthCookie. The FormsAuthenticationModule.Authenticate event could be used similarly by setting an HttpContext.User:
// Global.asax
void FormsAuthentication_OnAuthenticate(object sender, FormsAuthenticationEventArgs e) {
// check for postback somehow
if (Request.Url == "MyPage.aspx" && Request.Form["MySuperSecret"] == "123") {
e.User = new GenericPrincipal(new GenericIdentity(), new string[] { });
}
}
When the session timeout happens the user's session (and page information) get disposed, which would mean the eventual postback would fail. As the others have suggested there are some work arounds, but they all assume you don't care about authentication and security on that particular page.
I would recommend using Ajax to post back silently every 10 mins or so to keep it alive, or increase the timeout of the session as you suggest. You could try to make a page specific section in your web config and include in there a longer timeout.
I handled this once by adding the form value to the database, identified by the remote IP instead of user ID.
( HttpContext.Request.UserHostAddress )
Then, after login, you can check to see if the current user's IP address has a row in the database, and perform the required action.
Michael

Resources