asp.net mvc 3 reset password by admin and force user to change it - asp.net

I'm using asp.net Membership, I develop an admin page who can regenerate a temp password to send to the user, then when the user log on for first time, the password must be changed, but I cant figure out who to know if the password was reseted.
I tried something like in a base controller:
if (user.LastPasswordChangedDate >= user.LastLoginDate)
{
filterContext.Result = RedirectToAction("ChangePassword", "Account");
}
But, I already have updated the LastLoginDate because the ChangePassword Action need to be with a autenticated user.
I was thinking when reseting the password to lock/unlock the user to get updated the "LastLockoutDate" and do:
if (user.LastPasswordChangedDate >= user.LastLockoutDate)
{
filterContext.Result = RedirectToAction("ChangePassword", "Account");
}
But, I can't find a method to do manual lockout
Thanks!!!

There's a lot of things you could do, some would depend on how your system works. For instance, you could store a specific piece of data in the Comment field, if you're not using comments.
Or, if you don't use the "Approved" bit (that is, when you create new users you do not require them to validate an email or something, but instead create them with IsApproved set to true) then you can set IsApproved to False and force a password change if it's false.
There is no method to access much of this data in the Membership API, you just have to access it from you database.
You could also store this in the Personalization provider.
Another option is to simply avoid storing this in the Membership database, and instead just add a table or a field in your apps data to deal with this.

Related

MVC - how can I store a variable for the duration that a user is logged in

I have a project in MVC. I would like to save a variable and have it accessible as long as the user is logged in, to get it or set it.
The reason for this is that the application uses the information I would put in there, to get data. I now need to add admin functions so an admin can see more then only his own results, and therefore I would need to change this ID, depending on what result he wants to see.
I have tried using a session, but the problem I have with that is that when the user closes the website, and at a later time returns, he is still logged in, but the session variable is null.
I also tried to add a property to my base class. I was able to set it, but when I tried to get it in a different controller, the property was null as well.
What is the best/fastest/correct way to do this? I would prefer to not use the database for this, if possible.
What you are looking for is a "Session". On login you can just do
Session["Key"] = "Value";
And on logout you can empty the field
Session["Key"] = String.Empty;
You can read more about sessions here: https://msdn.microsoft.com/en-us/library/ms178581.aspx

Is it alright to put sensitive data into the cache? ASP MVC

I currently implemented some "checkers" for my MVC application.
So far here is what i have,
Authorization(Form)
Authentication (Custom RoleProvider)
Action Filters(to make sure that the user won't put any bogus id numbers or try accessing the other's data by editing the GET url.
I have several questions regarding the best practices for cache on ASP MVC.
Here is my implementation of my login:
[HttpGet]
[ActionName("login")]
public ActionResult login_load()
{
return View();
}
[HttpPost]
[ActionName("login")]
public ActionResult login_post(string uname,string pword)
{
using (EmployeeContext emp = new EmployeeContext())
{
//h student log = new student();
int success = emp.login.Where(x => x.username == uname && x.password == pword).Count();
if (success == 1)
{
int id = (from logs in emp.login
join rol in emp.roles on logs.role equals rol.id
where logs.username == uname
select logs.id).First();
FormsAuthentication.SetAuthCookie(uname, false);
HttpRuntime.Cache.Insert("id", id);
return RedirectToAction("Details", "Enrollment", new { id = id});
}
return View();
}
}
(I plan on implementing H&S as soon)
Anyway, here are my concerns so far:
For security concerns, would it be fine to store something like id's on cache? or it's better if i use sessions ?
Let's say i successfully logged in, and i add another line of this code :
HttpRuntime.Cache.Insert("id", id);
Is it going to edit my previous record or it's going to add another entry?
I have this code from my Custom RoleProvider, HttpRuntime.Cache.Insert(cacheKey, roles, null, DateTime.Now.AddMinutes(_cacheTimeoutInMinute), Cache.NoSlidingExpiration); and i believe that they are "fired" everytime i ask a controller with a protection of [Authorize(Role="users")]. So does it make a new entry or it edits the previous/existing one?
Should i worry about deleting/clearing my cache as soon as the user decided to log out? my role provider timeout is currently set to 20 minutes
I need the id because aside from the username, it is my unique identifier and i use it to compare on whatever id the user is trying to access.
I am thinking if it would be possible to edit the cache and use it against my application.
Don't worry about storing the ID, you need to go back and refactor to use the inbuilt identity stuff that's in the box for MVC. Looking at your code I can only assume that this system would store passwords in plain text. You will not pass any compliance with a system like this.
Rule of thumb when it comes to "is this secure" is don't write it yourself. Find a proven product and use that.
If for whatever reason the inbuilt identity system that is provided with MVC doesn't work for your requirements, have a look into this: https://github.com/brockallen/BrockAllen.MembershipReboot
FYI:
Identity system is the service that logs people in, out and manages the logged in user. Feel free to head over to this to learn more about the inbuilt system for MVC: http://www.asp.net/identity/overview/getting-started/introduction-to-aspnet-identity
For security concerns, would it be fine to store something like id's on cache? or it's better if i use sessions ?
In this case it doesn't make a lot of difference. However, the cache cannot be distributed across multiple web servers. Session state can by changing the <sessionState> section of the web.config file. So you are building an inherent limitation in scalability into your application by using cache.
Let's say i successfully logged in, and i add another line of this code :
HttpRuntime.Cache.Insert("id", id);
Is it going to edit my previous record or it's going to add another entry? I have this code from my Custom RoleProvider, HttpRuntime.Cache.Insert(cacheKey, roles, null, DateTime.Now.AddMinutes(_cacheTimeoutInMinute), Cache.NoSlidingExpiration); and i believe that they are "fired" everytime i ask a controller with a protection of [Authorize(Role="users")]. So does it make a new entry or it edits the previous/existing one?
First of all, you have a major flaw in your code. Cache is intended to be shared between all users on the site. So, when you insert a value, such as HttpRuntime.Cache.Insert("id", id);, all of the users will see it. If you are using this value to lookup data later, then the user data will always be for the last user that signed in.
You can fix this by adding adding a value unique to the user to the key.
var key = this.User.Identity.Name + "|Id";
HttpRuntime.Cache.Insert(key, id);
Note I am using a pipe character as a separator here. This is assuming the user name doesn't allow a pipe character (which you would also need to ensure).
Secondly, using a proper cache pattern means that you will never need to worry about whether "id" exists because you have already made that check. Using the cache typically looks like this.
public static string GetUserID()
{
// Check whether the user is logged in
if (!HttpContext.Current.User.Identity.IsAuthenticated) {
return 0;
}
// Make a UNIQUE key that can be used for this scenario
var userName = HttpContext.Current.User.Identity.Name;
var key = userName + "|Id";
// Attempt to get the ID from the cache
var id = HttpRuntime.Cache[key];
// A null value indicates there was no value in the cache
if (id == null)
{
// No ID in the cache, look it up from the database
using (EmployeeContext emp = new EmployeeContext())
{
id = (from user in emp.login
where user.username = userName
select user.id).First();
}
// Store the ID from the database into the cache
HttpRuntime.Cache.Insert(key, id,
// No Dependencies
null,
// No absolute expiration (mimic the behavior of forms authentication)
System.Web.Caching.Cache.NoAbsoluteExpiration,
// Timeout 20 minutes after the last access
// (to mimic the behavior of forms authentication)
new TimeSpan(0, 20, 0),
// Setting to NotRemovable ensures that if the
// application pool restarts, you don't lose your cache
System.Web.Caching.CacheItemPriority.NotRemovable,
// No callback needed here
null);
}
return (string)id
}
Of course, you can improve performance if the value is available at login by inserting it into the cache directly, but you need to ensure you use the same key in that case.
Session is probably a better choice in this scenario, but either way you should make use of this pattern to double check you have a value before returning it to the user.
Should i worry about deleting/clearing my cache as soon as the user decided to log out? my role provider timeout is currently set to 20 minutes
If you use Session state instead of cache this is much easier. Simply call Session.Abandon() when the user logs out.

How do I add impersonation in MVC ASP.NET Identity 2.0

I am wondering how I add user impersonation on mvc identity 2.0, I seen some people using this:
FormsAuthentication.SignOut();
FormsAuthentication.SetAuthCookie(user.UserName, false);
This wont work for me it wont even sign out I use :
AuthenticationManager.SignOut()
So how do I go along doing this I have admin panel what lists users, I get the userId or userName, what exactly do I have to do? I have never used Claims so I dont understand it much I wont need to revert back to user they can just logout for now.
Here is the solution for anyone who else is having this issue - :
var user = _db.AspNetUsers.Single(a => a.Id == id);
var impersonatedUser = UserManager.FindByName(user.Email);
var impersonatedIdentity = UserManager.CreateIdentity(impersonatedUser, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = false }, impersonatedIdentity);
Thanks for this question as it helped me find a number of solutions including yours and #trailmax. After some thought I went about this a different way, as I just needed to change some of the Claims to do the impersonation. I call this semi-impersonation, as it just changes a few things rather than totally change the user.
Like trailmax I have written a blog post on my approach with all the code. Below I have summarised how it works.
I add a session cookie with the impersonation information I needed to change in the current user to allow them to access information belonging to another user. I my case I had a key to some data.
I then use the new MVC's 5 AuthenticationFilter OnAuthentication method to a) look for the impersonation cookie. If it found it then it changed the Claims in the current ClaimsPrincipal, which the filter would then propagate through the application.
Coming out of impersonation mode was achieved by deleting the cookie, which you do by setting its expire date to a date prior to now.
The benefits are much more control over the level of access, but it won't work in all cases. In my article I compare my approach with #trailmax's approach to bring out the benefits of each implementation.

Asp.net, where to store the username of logged in user?

When a user log into my asp.net site I use the following code:
FormsAuthentication.RedirectFromLoginPage(userid, false);
As I often need to use the userid I can then later get the userid by:
string userid = System.Web.HttpContext.Current.User.Identity.Name;
Now I also want to show the logged in username on each page and my questions is therefore where do I place the username best if I need to use it on every page. User.Identity.Name is already taken by the userid so I can't use that one. Another solution would be to get the username from the database on each page, but that seems like a bad solution.
So: Is the best way to use Sessions to store the username?
There are essentially 6 different ways to store information, each with it's own benefits and drawbacks.
Class member variables. These are only good for the life of one page refresh.
HttpContext variables. Like class member variables, only good for one page refresh.
ViewState, these are passed from page to page to keep state, but increase the size of the downloaded data. Also, not good for sensitive information as it can be decoded.
Cookies. Sent on each page request. Also not good for sensitive information, even encrypted.
Session. Not passed to the end user, so good for sensitive information, but it increases the resource usage of the page, so minimizing usage for busy sites is important.
Authentication Cookie User Data - This is like like cookies, but can be decoded with the authentication data and used to create a custom IIdentity provider that implements your desired Identity information, such as Name or other profile information. The size is limited, however.
You can store just about anything in SessionState in asp.net. Just be careful and store the right things in the right places (you can also use ViewState to store variables.
Check this out for how to use SessionState to store and retrieve variables across postbacks.
public string currentUser
{
get { return Session["currentUser"] as string; }
private set { Session["currentUser"] = value; }
}
Using sessions isn't a bad idea but make sure to check for NULL when retrieving the values for when the sessions time out.
Or you could pass the variable through in the URL e.g
/Set
Response.Redirect("Webform2.aspx?Username=" + this.txtUsername.Text);
/Read
this.txtBox1.Text = Request.QueryString["Username"];

ASP.NET Membership - keep users to use previous passwords

I created a Membership login system for my client, now they do NOT want the user to use one of his 5 last passwords when it comes time to create a new one.
Is that something that is build in or how could I accomplish that?
This feature doesn't exist on asp.net membership login system.
You must implement it by yourself, on the automatic-creating page of changing password.
You need somewhere to save the previous hash list of your users passwords, and check this list, just before accepting a password change.
Update
Where to start:
Start from the all ready existing password change control.
Here is a password change example.
http://www.asp.net/cssadapters/Membership/ChangePassword.aspx
In this control, (that you can easy drag and drop on your page) capture the events,
<asp:ChangePassword ID="ChangePassword1" runat="server"
onchangingpassword="ChangePassword1_ChangingPassword" ... >...
Make your function to check for old passwords
protected void ChangePassword1_ChangingPassword(object sender, LoginCancelEventArgs e)
{
if (PasswordFoundOnList())
{
... show an error....
e.Cancel = true;
}
}
Now save somewhere the last passwords, for example you can saved them on user profile, or on your database.
here are some more informations for user profile.
http://www.asp.net/Learn/Ajax/tutorial-03-cs.aspx
Hope this help you make it.
Check this awesome post by Ronan Moriarty:
Implementing Password History using a Custom Membership Provider
It's an extensive post and I used option 2 as he describes. It has helped me implement what you ask. It's working great here.

Resources