I am using asp.net MVC 5 identity 2.0
The administrator is able to change user’s role but used must re-log to see the changes. First thought was to re-log user manually but I failed. After that I thought of dynamically changing user’s role or something else. Could you provide me the right way?
I set user’s role using UserManager.AddToRolesAsync
I have tried a lot of things like:
var memberUser = Membership.GetUser(user.UserName.ToString());
if (memberUser.IsOnline)
{
FormsAuthentication.SignOut();
}
or also try to clean up my cookies.
I dunno how I can sign out another user.
Also I have read articles like these
http://w3facility.org/question/mvc-5-addtorole-requires-logout-before-it-works/
How do I forcefully propagate role changes to users with ASP.NET Identity 2.0.1?
How to force logout user when his/her username is changed by another user?
ASP.net Identity 2.0 Sign-out another user
Have a look at the answer provided by Hao Kung on this post he describes exactly how to solve this using the SecurityStamp .
https://stackoverflow.com/a/19505060/1454538
So the primary purpose of the SecurityStamp is to enable sign out
everywhere. The basic idea is that whenever something security related
is changed on the user, like a password, it is a good idea to
automatically invalidate any existing sign in cookies, so if your
password/account was previously compromised, the attacker no longer
has access.
In 2.0.0 we added the following configuration to hook the
OnValidateIdentity method in the CookieMiddleware to look at the
SecurityStamp and reject cookies when it has changed. It also
automatically refreshes the user's claims from the database every
refreshInterval if the stamp is unchanged (which takes care of things
like changing roles etc)
This should get you going.
Related
I'm using external logins for my asp.net core mvc website, and when the login completes I want to store the social info they used to login (such as username, profile image, etc.) as claims in the user's identity...
So I run code like this in my account controller after a successful login:
var authClaim = user.Claims.FirstOrDefault(c => c.ClaimType == authToken.Name);
if (authClaim == null)
externalClaims.Add(new Claim(authToken.Name, authToken.Value));
else
authClaim.ClaimValue = authToken.Value;
if (externalClaims.Any())
await _userManager.AddClaimsAsync(user, externalClaims);
await _userManager.UpdateAsync(user);
however when I attempt to do this, the claims table is duplicating the claims rather than updating them as I expected, so every time the user logs in I get another collection of records in the table for that user that are identical to the last.
do I have to delete them and re-add them instead on every login? if not, how do I update existing claims without duplicating them?
I'm doing it on every login in case the user has changed their profile or other info (and to make sure I have the most up to date token).
I'm also curious why I add the claims to the main Identity of the user. The User has a property called ExternalClaims, but it is empty and there doesn't appear to be any way to update it. It seems to me this is a better place to put these third-party Claims, but I can't for the life of me find any way to modify it...
either way, I'm sure I'd have the same problem if I use this code, so is the proper course to delete the claim on login and always add it new, or should I be doing something differently?
I'm working on a project with Asp.Net MVC 5 and Asp.Net Identity and I'm using two factor authentication. For the login I use:
var result = await SignInManager.TwoFactorSignInAsync(model.Provider, model.Code, isPersistent: model.RememberMe, rememberBrowser: model.RememberBrowser);
which is the default code that came with the new project. However, I also need the ability for a user to "trust" or "remember" a browser, similar to how banks can indicate if this was the first time you have signed in from a particular browser/pc.
My question is around the RememberBrowser property on the sign in method and what .NET Identity does with this data. I want the list of saved browsers and the ability to revoke access to one/and-or all of them. Is that possible within the Identity framework? Also, can I tell if a browser has been "trusted" before by some type of lookup?
Edit:
Maybe it's a good idea to save the browser info in the database and check on login instead of the cookie? That way it can be shown as a list with the ability to delete it. What I'm looking for is what to save and how to integrate it with the Asp.Net Identity without having a security risk.
Edit 2
Here's an example from a website that is already using this:
Edit 3
Maybe this can be implemented as another step for authentication. So basically we'll have a 3 factor authentication:
First user logs in with user/pass
Then we'll check if the 2FA is enabled and get the code if necessary
We get the user's aser agent and IP and check the database if it's new. Then notify if necessary.
So I'm guessing an new cookie should be added to save browser's info. However, we should be able to invalidate this cookie along with the 2FA cookie.
RememberBrowser sets a cookie that allows the 2FA step to be skipped. There is no central way to track this though it would be easy enough to log, however the results may not be accurate because people can delete cookies manually. There's no way to invalidate it I believe but it doesn't really matter as you can invalidate their session and the user is will be required to login with their password again.
Not sure whether saving browser info adds value as browser info is gonna be same for different users (using same browser and version) unless you save requestor IP as well; and saving requestor IP has too many complications.
How about adding a custom claim to the token if user has set RememberBrowser and then do your logic based on this custom claim? For eg, set a custom claim your_claim_name and set a Guid.NewGuid() to it if RememberBrowser is true. Also save the username, this guid and status flag in database . When a request comes, check whether your custom claim is present, if yes query the table with the custom claim value and username to check whether the entry is still active.
You can either delete the entry or soft delete (set the status) the entry for an user so that when next request comes you can perform your required logic.
I have an asp.net web form. when a user authenticate, it create a Secured cookie called .aspxauth
uppon logout, I call these 2 methods
FormsAuthentication.SignOut();
Session.Abandon()
Problem is that we had penetration test and if I steal the cookie, logout and manually reinsert the cookie, I become loggued in again. So the .aspauth isn't invalidated server side.
I've googled it and I can't find the answer to that security breach.
Microsoft has acknowledged this issue here: https://support.microsoft.com/en-us/kb/900111
They offer several ideas for mitigating this vulnerability:
protect the application by using SSL
Enforce TTL and absolute expiration
Use HttpOnly cookies and forms authentication in ASP.NET 2.0
Use the Membership class in ASP.NET 2.0
Regarding the last one, I'll paste the contents from the site for convenience/preservation:
When you implement forms authentication in ASP.NET 2.0, you have the option of storing user information in a Membership provider. This option is a new feature that is introduced in ASP.NET 2.0. The MembershipUser object contains specific users.
If the user is logged in, you can store this information in the Comment property of the MembershipUser object. If you use this property, you can develop a mechanism to reduce cookie replay issues in ASP.NET 2.0. This mechanism would follow these steps:
You create an HttpModule that hooks the PostAuthenticateRequest event.
If a FormsIdentity object is in the HttpContext.User property, the FormsAuthenticationModule class recognizes the forms authentication ticket as valid.
Then, the custom HttpModule class obtains a reference to the MembershipUser instance that is associated with the authenticated user.
You examine the Comment property to determine whether the user is currently logged in.
Important: You must store information in the Comment property that indicates when the user explicitly signed out. Also, you must clear the information that is in the Comment property when the customer eventually signs in again.
If the user is not currently logged in as indicated by the Comment property, you must take the following actions:
Clear the cookie.
Set the Response.Status property to 401.
Make a call to the Response.End method that will implicitly redirect the request to the logon page.
By using this method, the forms authentication cookie will only be accepted if the user has not been explicitly signed out and the forms authentication ticket has not yet expired.
Read this article about Session fixation and how to get rid of it once and for all:
http://www.dotnetfunda.com/articles/show/1395/how-to-avoid-the-session-fixation-vulnerability-in-aspnet
This remains an issue in .NET Framework. Everyone seems to think Session.Abandon() is the answer, but the sad truth is that command does not invalidate the session on the server's side. Anyone with the right token value can still resurrect a dead session, until the session expires based on the Web.config settings (default = 20minutes).
A similar questioner posed this question a long time ago here:
Session Fixation in ASP.NET
Most of those links are dead, and Microsoft has no new news on the topic.
https://forums.asp.net/t/2154458.aspx?Preventing+Cookie+Replay+Attacks+MS+support+article+is+now+a+dead+link
Worse still, you're still vulnerable to this cookie replay attack even if you're implementing a completely stateless MVC application and don't use the Session object to store data between views. You can even turn off session state in the web.config settings and still replay cookies to gain access to a logged-out session.
The true solution is hack-y and described here, and you need to have session data enabled InProc to use it.
When the user logs in, set a boolean value in the session data, like Session["LoggedIn"] = true;, which is stored on the server side.
When the user logs out, set that value to false.
Check the session value on every request--an attacker trying to replay a session isn't going to be nice to you and come in through the Login page only. It's probably easiest to do this using a custom filter and registering it globally in the global.asax file (so you don't have to duplicate the code everywhere, or attribute every controller/method).
Even if the attacker has all the cookie values, they won't be able to re-use that same session ID, and the server will automatically delete it once it reaches the specified timeout.
if you are using the FormsAuthentication, you can use this code. By using this code you can destroy the created cookies by setting the Expire property of HttpCookie. It will help you:
FormsAuthentication.SignOut();
Session.Clear();
Session.Abandon();
Session.RemoveAll();
// clear authentication cookie
HttpCookie httpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, "");
httpCookie.Expires = DateTime.Now.AddYears(-1);
Response.Cookies.Add(httpCookie);
I have a ASP.NET MVC site with a CAS server set up as the authentication type. I also have a separate database with a Users table and a Roles table (with a User being related to one or more roles). A User is only able to log into the system if the Username is both in the User table and on the CAS system. I have this solution working.
My problem is i now need some form of trigger on User.IsAuthenticated so i can track the current User (from my database), without the possibility that i am trying to allow tracking of a User that has logged out. What I've been thinking is i need to add the User to the HttpContext but i am not sure how to trigger the clearing of the User if the CAS session times out or if the User Logs out.
I also wish to have some functionality such as User.IsInRole (again using my database, not ASP.NET) but am not sure how to go about implementing this. I suppose if i can successfully add the User to the HttpContext then a IsInRole method would simply be a User.Roles.Contains(string role) method but how can that then be used if i wish, for example, to use a method with the DataAnnotation [Authorize(role = "ExampleRole")].
I have looked at questions such as How do I create a custom membership provider for ASP.NET MVC 2? but this doesn't work for me (possibly to do with me using the CAS authentication?)
Any guidance or background reading would be appreciated as i'm really not sure where i should even start. I have read up on GenericPrinciple, IPrinciple and IIdentity but I'm struggling to see how i can apply them to my current project.
Ended up with a custom Authorise Attribute that uses the CAS logon to check the user exists in my database. It also checks the roles of that user. I also used a static class to save the current user in the session with a logout method that abandons the session when the user logs out.
I have kind of a two parter for you. This link does a really good job of explaining how to replace the HttpContext User with your own object: http://bradygaster.com/custom-authentication-with-mvc-3.0
His approach uses MVC filters, but you can also catch the Authentication event in the Global.asax file. Using the forms system with your own implementation can be trivial or not depending on what you're doing, but it boils down to calling FormsAuthentication.SetAuthCookie and .SignOut, amidst your own logic.
public static void FormsLogin(this User user, bool persist)
{
FormsAuthentication.SetAuthCookie(user.DisplayName, persist);
user.AddHistory("Login event.", HistoryType.Login, "SYSTEM");
Users.OnUserLogin(user);
SetLastActivity(user);
}
public static void FormsLogout(this User user)
{
FormsAuthentication.SignOut();
}
Lastly, once you've got the login stuff working out, you can use your own more complex permission system by making a custom Auth Attribute. I remember piecing this together from some other answers and articles but I can't seem to find the sources at the moment, I will try and edit with sources for credit where it's due, if I find them. For now, all I can offer is this gist which offers up one of the attributes I use: https://gist.github.com/1959509
Keep in mind the only really relevant part there is the override of OnAuthorization, which does the actual work.
I am using .net membership to manage my user roles. Currently users are suspended after a long period of inactivity. Is there a membership api to unsuspend the user?
There is no 'suspension' as such in the Membership Provider; however, there are two properties that will affect the ability of a user to login to the system:
In the MembershipUser class, let's look at:
MembershipUser.IsLockedOut: This property indicates that a user has been locked out of the system by trying to log in with the incorrect password more than the allowed number of times. The web.config would have that number.
Notice that you cannot explicitly lockout a user programmatically. Only a user herself can get locked out by trying incorrect passwords for her account.
MembershipUser.IsApproved: You can approve or disapprove a user and that property will define whether a user can be authenticated or not. This is probably the equivalent to a Suspended user. You simply set the MembershipUser.IsApproved to false and update the user with the MembershipProvider.UpdateUser(MembershipUser) method. Conversely, you would set the property IsApproved to true if you want to allow the user to log in again.
Hopefully, this will clarify the capabilities of the Membership provider, but it is strange to see that a user has been 'suspended' from the system due to inactivity. Are you sure it is not one of the two options discussed above?
If suspend and unsuspend here mean lock/unlock you can try:
MembershipUser user = Membership.GetUser("name");
user.UnlockUser();