Single login in asp.net - 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");
}

Related

Force Logout all devices in mvc 4 application?

I have mvc 4 project with default Account Controller and UsersContext as DbContext. When a user, Suppose User1 logged in with REMEMBER ME checked on mobile. And next day User1 login in Laptop and changed its password, now User1 opened his mobile it is already logged in even when password is changed.
Is there any way by which i can force that User1 to Logout all the Devices,
without storing any session id in database?
I imagine you could store a "last password change date" in the cookie. On authentication, if the user has changed his password since the stored date, then do not authenticate the user.
You should probably store a hash of the last password change date, so that it can't be tampered with from the client side.
Have a flag in the database that checks users on Session_Start that invalidates their session if that flag is set. May not necessarily use a boolean, you can use a DateTime value and invalidate all sessions that started prior to that time. This could be done by checking a value stored in a cookie upon login.
There is nothing built into ASP.NET MVC (that I know of) that provides this functionality
I know this is an old topic but I ran across this today. The cause was slightly different, but I needed to do the same thing - log off a user if 'remember me' had been chosen.
The cause in my case was a change of database. I changed the database name in my connection string (from a 'test' DB to a 'dev' DB), and I will still logged in after running the project, which caused a problem because the user did not actually exist in this new DB.
So in Global.asax I did the following:
private ApplicationUserManager _userManager;
public ApplicationUserManager UserManager
{
get
{
return _userManager ?? HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
}
private set
{
_userManager = value;
}
}
protected void Session_Start()
{
if (User.Identity.IsAuthenticated)
{
var user = UserManager.FindByName(User.Identity.Name);
if (user == null)
{
HttpContext.Current.GetOwinContext().Authentication.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
Response.Redirect("/", true);
}
}
}
You need to redirect and terminate execution of the current page (by passing true) because (as I understand it) the sign out does not affect the current request, so the page that was loading will still load as if the user is logged in. Anyone feel free to correct, clarify or expand upon this.

Session Log Out Issue

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.

Authentication and Security in my website - need advice please

I am using database with a list of username/passwords, and a simple web form that allows for users to enter their username/password.
When they submit the page, I simply do a stored procedure check to authenticate. If they are authorised, then their user details (e.g. username, dob, address, company address, other important info) are stored in a custom User object and then in a session. This custom User object that I created is used throughout the web application, and also in a sub-site (session sharing).
My question/problems are:
Is my method of authentication the correct way to do things?
I find users complaining that their session have expired although they "were not idle", possibly due the app pool recycling? They type large amounts of text and find that their session had expired and thus lose all the text typed in. I am uncertain whether the session does really reset sporadically but will Forms Authentication using cookies/cookiless resolve the issue?
Alternatively should I build and store the User Object in a session, cookie or something else instead in order to be more "correct" and avoid cases like in point #2.
If I go down the Forms Authentication route, I believe I cannot store my custom User object in a Forms Authentication cookie so does it mean I would store the UserID and then recreate the user object on every page? Would this not be a huge increase on the server load?
Advice and answers much appreciated.
L
It doesn't really care whether you use your own authentication system, or the default membership providers when using such a simple scenario.
You should avoid using the InProc session state when the app might recycle some times a day. Rather store your session into a database (SqlSessionState) or use a StateServer. Then the application pool can recycle all day without interferring with your sessions. Setting the session timeout to 60 minutes or something, will solve the remaining issues. Never use cookieless sessions (unless you know what you're doing), as they make it way too easy to steal one's session.
Just store it into the session (or profile if you use the default membership provider). Not only is a cookie easily readible, it is also limited to 4 KB.
No, you will have a profile where all the user information is stored. It doesn't really matter whether you use forms authentication or a custom system that stores it's data into SqlSessionState. The membership provider will store the Profile ID into a cookie, same as the session state will save the Session ID into a cookie.
You can use ASP.NET Membership, Roles, Forms Authentication, and Security Resources
I will give an example using c#
For reference Forms Authentication in ASP.NET 2.0
//code for checking user name & password
protected void btnlogin_Click(object sender, EventArgs e)
{
try
{
if (txtUserName.Text.Trim() != "" && txtPassword.Text.Trim() != "")
{
User obj = objUser.UserAuthenticate(txtUserName.Text.Trim(), txtPassword.Text.Trim());
if (obj != null)
{
//To set AuthenticationCookie of usertype "User"
SetAuthenticationCookie("User", obj.UserID.ToString(), obj.DisplayName);
HttpCookie usercookie = new HttpCookie("LoginTime");
usercookie.Value = DateTime.Now.ToString();
Response.Cookies.Add(usercookie);
HttpCookie namecookie = new HttpCookie("LoginName");
namecookie.Value = obj.DisplayName;
Response.Cookies.Add(namecookie);
}
else
{
lblMsg.Text = "Invalid Username or Password.";
}
}
else
{
//lblMsg.Visible = true;
}
}
catch (Exception ex)
{
//lblMsg.Visible = true;
throw ex;
}
}
private void SetAuthenticationCookie(string role, string userid, string name)
{
string userdata = "logintype=user|role=" + role + "|email=" + txtUserName.Text.Trim() + "|name=" + name;
FormsAuthenticationTicket faTicket = new FormsAuthenticationTicket(1, userid,
DateTime.Now, DateTime.Now.AddHours(+1),
false, userdata);
HttpCookie authCookie = new HttpCookie( FormsAuthentication.FormsCookieName,//"martinfernandez#ispg.in",
FormsAuthentication.Encrypt(faTicket));
authCookie.Expires = faTicket.Expiration;
Response.Cookies.Add(authCookie);
}
//code inside global.asax.cs
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
if (Context.User != null && Context.User.Identity is FormsIdentity && Context.User.Identity.IsAuthenticated)
{
FormsAuthenticationTicket faTicket = FormsAuthentication.Decrypt(Request.Cookies[FormsAuthentication.FormsCookieName].Value);
string[] userdata = faTicket.UserData.Split("|".ToCharArray());
string logintype = "";
string email = "";
string uname = "";
string roleString = "";
foreach (string s in userdata)
{
string keyname = s.Split("=".ToCharArray())[0];
if (keyname == "logintype")
{
logintype = s.Split("=".ToCharArray())[1];
}
else if (keyname == "role")
{
roleString = s.Split("=".ToCharArray())[1];
}
}
string[] rolesArray = roleString.Split(";".ToCharArray());
Context.User = new System.Security.Principal.GenericPrincipal(new FormsIdentity(faTicket), rolesArray);
}
}
Just to touch on point #4 - it would be more efficient memory-wise to not store everyone's "User" object in memory, and re-create the object each HTTP request. This way you also re-verify the login details-- what if someone's account is compromised and the actual user changes their password to try and protect their account, but the "bad user" has already logged in? Under your security mechanism, the "bad user" can keep browsing away since the user data is cached and not re-verified each postback.
Here are the some general security measures that beginner and Advance Web Developer must follow.
#15 Steps To Secure Your Website
1 : Prevent Image Hotlinking (IMP)
Image hotlinking is the process of using someone else’s Image URL in our Website and using their bandwidth. In order to prevent this mystery, we can prevent access for external server by adding following line in code.
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?yourdomain.com [NC]
RewriteRule \.(jpg|jpeg|png|gif)$ - [NC,F,L]
2 : Prevent CSRF (Cross Site Request Forgery) Attacks
In order to prevent CSRF attacks on your GET and POST requests for form submission, you can use following 2 techniques.
The first it to include a random token with each request, this is a unique string that is generated for each session.
The second method is to use random name for each form field.
3 : Prevent Directory Access / Disable Indexing
Add the following line to your .htaccess file.
Options -Indexes
4 : Secure your Private and CMS Login with IP restrictions
IP restriction is a bit way advanced yet effective method to stop the unauthorized personnel to access a particular area of your website.
Here is an example htaccess code to IP restrict the access to a particular location.
ALLOW USER BY IP
<Limit GET POST>
order deny,allow
deny from all
allow from 1.2.3.4
</Limit>
5 : Protect your .htaccess file
You can write this below piece of code in your htaccess file which do not let any others access your htaccess file.
<Files ~ “^.*.([Hh][Tt][Aa])”>
order allow,deny
deny from all
satisfy all
</Files>
6 : Function access rule
By adding "_" as a prefix for Function name, we can prevent function to be called from The Web publicly. This is the best practice when we need some specific function to be accessed via AJAX only.
7 : Lock down your directory and file permissions
File permissions define who can do what to a file.
"Read" = 4 : View the file contents.
"Write" = 2 : Change the file contents.
"Execute" = 1 : Run the program file or script.
8 : Prevent Cron Job to be run from Web Browser
By adding, following line of code in your page, you can protect your page to be accessed from a web browser.
if( ! $this->input->is_cli_request() ) {
die("Only CLI Requests Allowed");
}
9 : Hide admin pages to be crawled by Google
You do not want your admin pages to be indexed by search engines, so you should use the robots_txt file to discourage search engines from listing them.
10 : Disable Right Click on Page if not require
Disabling “right-click” as a way to view your website source code by inspect element to secure Website content for general users.
11 : Use Strong Password for CMS
Keep practice to set random Password with the special character only.
12 : Make Admin Directory Tough to guess
It may happen that Hackers can use scripts that scan all the directories on your web server for giveaway names like ‘admin’ or ‘login’ etc. and your significant stuff may get leaked.
13 : Change your database table prefix
Add a prefix (the mixture of project name and year) which would be hard to presume for a secured side.
To illustrate,
A) BPM Supreme => bpm14_download
B) Glickin => gk15_admin
C) TravelWorthy => tw16_user
14 : Prevent User's Password, that's as important as yours
Regarding Password Encryption algorithm, Use sha1 algorithm instead of tradition algorithm Md5 which is the very old way and becoming less secure nowadays as per sources.
Reference : http://php.net/manual/en/function.sha1.php
15 : Hide Error Log
During development Mode, keep error reporting "ALL" and once we go LIVE change it to "0" without forgetting. Over here
Reference : http://php.net/manual/en/function.error-reporting.php
My advice would be to use asp.net membership and roles (Microsoft). It is a very good security solution - login security, roles (permissions) and is stored in a SQLServer database (not sure if it can be stored elsewhere).
I use it on my site and you can use membership controls straight out of the box (login forms, change password, etc.) or you can roll your own.
The only tricky bit I found was setting up the membership tables, views and stored procs in my dB (you download a dB script), but really it was fairly straightforward to implement.
Here's a link to asp.net membership and roles

ASP.NET MVC Session across subdomains

In my website i have implemented custom session values. In which, on log on i set the session value to some object. This object is used to extract user specific data from db.
now the problem is If user logs in with : test1.somesite.com and logs off and again logs in with: test2.somesite.com that user is still receiving the data from object specific to test1.somesite.com.
the point is whichever site user first logs in with the second time if he logs in with another subdomain he is always getting the data from previous sub domain login.
on log out from specific domain i cleared all the sessions(tried everything): by putting HttpContext.session["UserDetail"] = null;, HttpContext.Session.Abandon() and also HttpContext.Session.Clear();
but nothing seems to work
and i also don't have much idea how session variables are treated across subdomains.
I mean if i initialize a session with one value by visiting test1.somesite.com will that value also be visible if on the same computer and on same browser i also open test2.somesite.com.
any help please
Sounds like a cookie issue. Try clearing out the session cookie. Something along the lines of:
if (!User.Identity.IsAuthenticated)
{
if (Request.Cookies["ASP.NET_SessionId"] != null)
{
Response.Cookies["ASP.NET_SessionId"].Expires = DateTime.Now.AddDays(-1);
}
Session.Abandon();
}
What you need to do is set your asp.net session id cookie to write to a wild card domain.
Response.Cookies("ASP.NET_SessionId").Domain = "yourdomain.com" // or "*.yourdomain.com"
So that the cookie can float to your subdomains.

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

Resources