Force Logout all devices in mvc 4 application? - asp.net

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.

Related

ASP.NET MVC Windows Authenticate with extending properties

I need help of experts!
I write ASP.NET MVC 4 Intranet application. I using Windows Authentication, the domain name get through User.Identity.Name. I have a database with the configured data context, where more complete information about the user: Last name, First name, E-mail, etc. As well as a list of user access groups.
Needed to make sure that a user open a program, has received the required access from the database, his name brought up in the upper right corner of the page.
Now I have realized that with the use of OWIN Asp.Net Identity. I created a base controller that inherits the other controllers, it ordered CurrentUser method for the user and his SignIn:
protected ApplicationUser CurrentUser
{
get
{
var curUser = AppUserManager.FindByName(User.Identity.Name);
if (curUser != null)
SignInManager.SignIn(curUser, true, true);
else
curUser = new ApplicationUser();
return curUser;
}
}
protected ApplicationSignInManager SignInManager
{
get
{
return HttpContext.GetOwinContext().Get<ApplicationSignInManager>();
}
}
I understand that these operations are unnecessary, when you refresh the page every time it is necessary to drag into the database, users receive and make SignIn, which is unnecessary.
I'm sure you can realize all without using Asp.Net Identity. For example by expanding IPrincipal User, adding him to the field name, which are needed when displaying pages and adding once Roles from the database and save all in Cookies.
Please, help me! And sorry for my bad english...

how to change the value of user.identity.name

I think this is a very fundamental question - but i am not sure how to do it.
I am trying to test an application with different user login ID's (because these users have different roles).The application uses the login information of the system user and has no login of its own. The user.identity.name is used to get the value. However I would like to override this value to test for different user logins. How can I do this?
When you set your authentication ticket, change it there. I'm assuming it's using Forms Auth (logging in as user).
FormsAuthentication.RedirectFromLoginPage("Joe",false);
If using Windows Authentication you could use impersonation.
Another alternative, if using Windows Authentication, is to modify your browser setting to prompt you for a login. Then login as the different user.
you could always mock it with something like Moq
Mock<ControllerContext> ControllerContextMock;
string UserName = "TestUser";
ControllerContextMock = new Mock<ControllerContext>();
ControllerContextMock.SetupGet(p => p.HttpContext.User.Identity.Name).Returns(UserName);
this is how I do my unit/behavior testing
per my Comment below I'm adding a wrapper around the get user Name
public string OverideName;
private string GetUserName()
{
string name;
if(OverideName != null && OverideName.Langth>0)
{
name = OverideName;
}else
{
name = User.Identity.Name;
}
return name;
}
For most older asp.net web form testing this is really the only way to test stuff
I'm wanting to do the same.
My thoughts are to create a "change identity" page (only accessible by those with admin roles in my application). They can then choose to be a different person / role for the purpose of testing the application.
Each page in my application tests to see if a session set user id and role is valid (set on first use of the application) and loads the page to show the information / functionality that that user / role is meant to see. So this "change identity" function would set the session user id and role to that of the user under test, and allow the person testing to behave as if they are the other person. Also providing a reset option to reset yourself back to you.
Simpliest solution is when user updates name - log him out, and ask for login.
its work for me

Is there any good reason why the authentication cookie and the session state cookie are two separate cookies?

Is there any good reason why ASP.NET's session state cookie and the Forms Authentication cookie are two separate cookies? What if I want to "tie" them to each other? Is it possible in an elegant way?
Right now, I am stuck with the following solution, which works, but is still ugly:
[Authorize]
public ActionResult SomeAction(SomeModel model)
{
// The following four lines must be included in *every* controller action
// that requires the user to be authenticated, defeating the purpose of
// having the Authorize attribute.
if (SomeStaticClass.WasSessionStateLost/*?*/) {
FormsAuthentication.SignOut();
return RedirectToAction("Login", "Account");
}
// ...
}
#RPM1984: This is what happens:
[HttpPost]
public ActionResult Login(LoginModel loginModel)
{
if (/* user ok */)
{
// ...
Session["UserID"] = loginModel.UserID;
Session["Password"] = loginModel.Password;
// ...
}
else
{
return View();
}
}
And it doesn't take much guessing to know what WasSessionStateLost does.
Session != Authentication
The session state cookie tracks the user's activity during a browser session.
The forms authentication cookie tracks the user's authenticated activity during a given time period, specified by the expiration date of the ticket and whether or not you have created a persistent cookie (e.g "Remember Me" checkbox).
You shouldn't be touching the session cookie itself, and all it contains is an identifier to tie the client session (browser) to the server.
If you need to access the session, use HttpContext.Current.Session.
What exactly are you trying to "tie" together?
What does SomeStaticClass.WasSessionStateLost do?
I'll start with a solution, then an explanation followed by a recommendation.
Create a custom authorization attribute:
Since your application defines Authorized as follows:
Logged in
Must have values in Session["UserID"] and Session["Password"]
you need to define your own AuthorizationAttribute
public class AuthorizedWithSessionAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
if(httpContext.Request.IsAuthenticated &&
Session["UserID"] != null && Session["Password"] != null)
return true;
// sign them out so they can log back in with the Password
if(httpContext.Request.IsAuthenticated)
FormsAuthentication.SignOut();
return false;
}
}
Replace all your [Authorize] attributes with [AuthorizedWithSession] and you shouldn't need to put session check code in your controllers.
I don't know enough about your application, but saving passwords in session (even worse in plain text) is not a secure thing to do.
In addition, as RPM1984 said, the session cookie and authentication cookie are separate.
Explanation:
Think of the session as a bucket of info (on the server side) with your name on it. ASP.NET can take and put stuff in that bucket. ASP.NET gives you a name, your session id, and puts it on the bucket so it can know which one is yours.
The authentication cookie tells ASP.NET that you're authenticated and stores your authentication name in it. The authentication name is usually set by the developer of the application and is usually a unique key (think primary key in a DB) to separate you from the other users.
Recommendation to be more secure:
Encrypt the passwords before your store them. This is not total security, but it beats storing passwords in plain text and of course, if someone were to get a hold of the encryption key, they can crack the passwords.
Rather than using session, which is short lived you could cache in the System.Web.Cache. With this you can add events that are called before an entry is removed and decide accordingly if the cache should be cleared. You can set a higher time-out value on that, with the added bonus that you're not storing the clear text password in a file or database anywhere. Another bonus is you won't be vulnerable to session hijacking.
Of course if the application pool recycles the cache is gone, and as it's in memory load balanced machines will be out of sync, but Velocity or another distributed, out of process cache system would solve that.
It's not perfect though, entries may be dumped due to pressure on the cache, and of course you know this is all a bad idea anyway, so I'll skip that lecture.

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

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