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
Related
I have an ASP.NET 3.5 application that I recently extended with multiple membership and role providers to "attach" a second application within this application. I do not have direct access to the IIS configuration, so I can't break this off into a separate application directory.
That said, I have successfully separated the logins; however, after I login, I am able to verify the groups the user belongs to through custom role routines, and I am capable of having identical usernames with different passwords for both "applications."
The problem that I am running into is when I create a user with an identical username to the other membership (which uses web.config roles on directories), I am able to switch URLs manually to the other application, and it picks up the username, and loads the roles for that application. Obviously, this is bad, as it allows a user to create a username of someone who has access to the other application, and cross into the other application with the roles of the other user.
How can I mitigate this? If I am limited to one application to work with, with multiple role and membership providers, and the auth cookie stores the username that is apparently transferable, is there anything I can do?
I realize the situation is not ideal, but these are the imposed limitations at the moment.
Example Authentication (upon validation):
FormsAuthentication.SetAuthCookie(usr.UserName, false);
This cookie needs to be based on the user token I suspect, rather than UserName in order to separate the two providers? Is that possible?
Have you tried specifying the applicationName attribute in your membership connection string?
https://msdn.microsoft.com/en-us/library/6e9y4s5t.aspx?f=255&MSPPError=-2147217396
Perhaps not the answer I'd prefer to go with, but I was able to separate the two by having one application use the username for the auth cookie, and the other use the ProviderUserKey (guid). This way the auth cookie would not be recognized from one "application" to the other.
FormsAuthentication.SetAuthCookie(user.ProviderUserKey.ToString(), false);
This required me to handle things a little oddly, but it simply came down to adding some extension methods, and handling a lot of membership utilities through my own class (which I was doing anyhow).
ex. Extension Method:
public static string GetUserName(this IPrincipal ip)
{
return MNMember.MNMembership.GetUser(new Guid(ip.Identity.Name), false).UserName;
}
Where MNMember is a static class, MNMembership is returning the secondary membership provider, and GetUser is the standard function of membership providers.
var validRoles = new List<string>() { "MNExpired", "MNAdmins", "MNUsers" };
var isValidRole = validRoles.Intersect(uroles).Any();
if (isValidRole)
{
var userIsAdmin = uroles.Contains("MNAdmins");
if (isAdmin && !userIsAdmin)
{
Response.Redirect("/MNLogin.aspx");
}
else if (!userIsAdmin && !uroles.Contains("MNUsers"))
{
Response.Redirect("/MNLogin.aspx");
}...
Where isAdmin is checking to see if a subdirectory shows up in the path.
Seems hacky, but also seems to work.
Edit:Now that I'm not using the username as the token, I should be able to go back to using the web.config for directory security, which means the master page hack should be able to be removed. (theoretically?)
Edit 2:Nope - asp.net uses the username auth cookie to resolve the roles specified in the web.config.
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.
I have a Asp.net web site built on C# with Forms Authentication. We use an Active Directory to authenticate the users, and everything works fine. But today we realized that it's possible to login to any account by just entering the username and click Login, without supplying any password! This is only happening on the development environment running on localhost (thank god!), but I don't like it...
I've never seen this behaviour before, and would really like someone to explain how this could happen. Is this a developer feature built by Microsoft? Or did someone at my office make a backdoor without telling the rest? I will investigate this last option further, but until then - have anyone encountered this before?
Big thanks in advance!
EDIT:
This is where the authentication returns true for every username I throw at it - with a blank password. Other passwords return false.
using (var context = new PrincipalContext(ContextType.Domain))
{
result = context.ValidateCredentials(username, password);
}
PrincipalContext is the default from System.DirectoryServices.AccountManagement
After some more investigation I found this on MSDN which states:
The ValidateCredentials method binds to the server specified in the constructor. If the username and password parameters are null, the credentials specified in the constructor are validated. If no credential were specified in the constructor, and the username and password parameters are null, this method validates the default credentials for the current principal.
and together with this information in the documentation of the constructor of PrincipalContext:
public PrincipalContext(System.DirectoryServices.AccountManagement.ContextType contextType, string name):
contextType: A System.DirectoryServices.AccountManagement.ContextType enumeration value specifying the type of store for the principal context.
name: The name of the domain or server for System.DirectoryServices.AccountManagement.ContextType.Domain context types, the machine name for System.DirectoryServices.AccountManagement.ContextType.Machine context types, or the name of the server and port hosting the System.DirectoryServices.AccountManagement.ContextType.ApplicationDirectory instance. If the name is null for a System.DirectoryServices.AccountManagement.ContextType.Domain context type this context is a domain controller for the domain of the user principal under which the thread is running. If the name is null for a System.DirectoryServices.AccountManagement.ContextType.Machine context type, this is the local machine name. This parameter cannot be null for System.DirectoryServices.AccountManagement.ContextType.ApplicationDirectory context types.
This leads me to conclude that since I don't use the name property in the constructor of the PrincipalContext, the domain controller will run under my own principal when on my dev machine. This could mean that it uses my users priveliges, which of course are much higher than the machine accounts the production servers are running as. This in turn could make all calls to Validate with nullas password automatically validate due to the higher level of privelige.
At least, this is my theory... Comments and thoughts are welcome, I will be closing this question soon.
Sounds like the problem is in the code. For a user to be AD authed the password needs to match. A security tokens is generated from AD, and this can't be done without the proper password or impersination (which also requires password).
Is the code using SELECT user FROM users WHERE password LIKE '%password%'? I've seen that done before! :(
Why don't you add null validation for password before calling ValidateCredentials? On a side note, client side authentication might help as well.
Why not you try to
handle NULL Parameter Exception.
check first both credentials have values.
using (var context = new PrincipalContext(ContextType.Domain))
{
if (string.IsNullOrEmpty(UserName) && string.IsNullOrEmpty(Password))
{
throw new ArgumentNullException();
result = null; // Or redirect to Login Page
}
else
{
result = context.ValidateCredentials(username, password);
}
}
The System.Security.Principal.WindowsIdentity.Impersonate function takes a System.intptr parameter, which seems awfully useless in my situation (with my limited understanding).
I am developing an intranet application that uses integrated security to authorize users page-by-page against a role associated with their Windows Identity. I have no passwords or anything of the sort. Simply a Windows username. For testing purposes, how could I possibly impersonate a Windows user based on their username? The "impersonate" method jumped out at me as obvious, but it takes an unexpected parameter.
Thanks in advance :)
In a nutshell, no. But you are on the right track. You either have to get the user by simulating a login with LoginUserA ( C Win32 Api ) or set your IIS site to Windows Authentication.
In that case, your Page will have a property named User of type IPrincipal, which you can then use to run as that user. For example ( sorry, C# code ).
IPrincipal p = this.User;
WindowsIdentity id = (WindowsIdentity)p.Identity;
WindowsImpersonationContext wic = id.Impersonate();
try {
// do stuff as that user
}
finally {
wic.Undo();
}
Are you using anything windows-specific from the WindowsPrincipal or is it just a handy way to get auth/auth without having to manage users? If you need to be windows-based, Serapth has the right method. If you are just really using it as a convenient auth/auth store, then you should probably write your code to interface with IPrincipal. You can then inject your own implementations of IPrincipal with the desired values into either the HttpContext.User or Thread.CurrentThread.Principal depending on the nature of your tests and app.
User tokens (the value that the IntPtr in Impersonate represents) represent more than the username. They are a handle into an internal windows context that include information about the user, authentication tokens, current security rights, etc. It's because of this that you can't impersonate without a password. You have to actually "log in" to create a token via the LogonUser method.
What I've done in the past is create a special "Test" user account with a password that I can just keep in code or a config file.
You shouldn't need to impersonate to check role membership. Simply use the constructor for a WindowsIdentity that takes a UPN (userPrincipalName) constructed from the username according to your UPN conventions, then create a WindowsPrincipal from that identity and use IsInRole to check membership in a group. This works on W2K3 and a Windows 2003 domain, but not in other circumstances.
var userIdentity = new WindowsIdentity( username + "#domain" );
var principal = new WindowsPrincipal( userIdentity );
var inRole = principal.IsInRole( "roleName" );
You may also want to consider using either the standard or a custom role provider that will allow you to use the Roles interface to check membership.
I'm creating an ASP.NET web application which I want to secure with Forms Authentication.
When the application is run for the first time, I want it to create a default administrator account so that the owner is able to log in and configure the application.
I managed to get something working for this by running the following method from the Application_Start method:
private static void InitializeMembership(MembershipProvider provider)
{
int total;
provider.GetAllUsers(0, 1, out total);
if (total == 0)
{
Membership.CreateUser("admin", "admin");
}
}
The problem is this fails with an error about the chosen password not being secure enough. Normally this would be fine as I do want to enforce a strong password, but in this specific case I want a simple password
Is there a way of disabling the check for just this call, or am I approaching the whole problem incorrectly?
I would ship the DATABASE with the admin user in there by default, and force that password to get changed on the first login.
This is helpful in two ways:
1) You know that the default admin will always be there
2) you don't have to maintain that user creation code that will only run at very random intervals.
Alternatively, you could make your default password be more complex.