I have been messing with this all night and it is really frustrating. I got the webpage to display finally but for some reason it is not working meaning that it shoots me back to my error page and states "Could Not Authenticate User Please Try Again!". I cant figure this out as this works perfectly find on my local machine that visual studios is installed on.
Please if someone can take the time to help out with this, ive been fighting with it all day. THanks
Class.cs
public bool IsUserInSetup(string groupName, UserPrincipal user)
{
PrincipalContext context = new PrincipalContext(ContextType.Domain, "DomainName");
GroupPrincipal group = GroupPrincipal.FindByIdentity(context, "GroupName");
if (user.IsMemberOf(group))
{
return true;
}
return false;
}
Authentication.aspx.cs
if (!IsPostBack)
{
if (Request.IsAuthenticated)
{
if (gv.IsUserInSetup("GroupName", user))
{
Session["userValue"] = UserPrincipal.Current;
Response.Redirect("Default.aspx");
}
else
{
lblInfo.Text = "Could Not Authenticate User Please Try Again!";
lblInfo.Text += "<br><b>Name: </b>" + User.Identity.Name;
lblInfo.Text += "<br><b>Authenticated With: </b>";
lblInfo.Text += User.Identity.AuthenticationType;
}
Once possible reason why the application might be failing when deployed on IIS is because the account you configured it to run under doesn't have sufficient privileges to access the Active Directory server. By default the application pool in IIS runs under a built-in ApplicationPoolIdentity account which is a local to the server account. You should go to the settings of the application pool in IIS and select a domain account with sufficient privileges.
This works when running locally in VS because you are running your application with your account which is probably a domain account with access to Active Directory.
Got the answer on another forum but I was doing a lot of extra work for no reason. Asp.net has a USER.ISINROLE("GROUPNAME") and i used that.
Related
I am trying to get information about the currently logged in user via a Windows service, specifically is the user is an admin level role or not. The service is properly collecting the currently logged in user, and I have code that works when the computer the service is running on is connected to the network, but I can't always guarantee the computer will be on the network when the service does this user level check.
Long story short, does WindowsIdentity require the computer be connected to the network to create an identity? I can't find anything online that clearly states if this is the case.
I only need to get whether or not the current user is an admin level role or not for the local system. I don't care if it's an admin at the domain level, although I understand this is probably going to be the case if the system is on a network.
If there is a better way to do this for my needs, I am happy to see other recommendations.
I have done some major googling and looked at a number of other SO answers, but none of them seem to work when the computer is not on the network. They did help me get a version that works when the computer is on the network though.
I also looked at the MS documentation for this and don't see anything clear about network needs. I may have missed something thought.
The below method works while on network.
private bool IsUserAdministrator(string accountName)
{
var result = false;
try
{
using (var identity = new WindowsIdentity(accountName))
{
var principal = new WindowsPrincipal(identity);
var adminSid = new SecurityIdentifier("BA");
result = principal.UserClaims.Any(c => c.Value.Equals(adminSid.ToString()));
}
}
catch (Exception)
{
// Exception handled by returning false
}
return result;
}
This method also works, when on network. The failure point while debugging is the new WindowsIdentity().
private bool IsUserAdministrator(string accountName)
{
using (WindowsIdentity identity = new WindowsIdentity(accountName))
{
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
Once again, when connected to the network, both of these either return 'true' when the user is an admin role, or 'false' when the user is not admin role.
When not connected to the network this fails and throws the exception {"There are currently no logon servers available to service the logon request.\r\n"}.
Is this an issue with WindowsIdentity or is something else causing this? Is this an LDAP issue?
Sorry, I realize there are multiple questions spread throughout this, but the number one issue is, does WindowsIdentity need network connection, and if yes, is there another way to achieve my goals?
I'm trying to do something that I don't even know if it is possible.
I have a web application based on C# that runs on a specific server. I want to build a code where the user introduces the domain where the app runs (this server depends on the client, for each client it runs on different servers obviously) and the app returns the local windows user accounts of that domain and information saying if the users are locked out or not.
I've tried to use Win32_UserAccount but it seems to get the users of the network I'm currently using.
Is this possible to do?
Thank you so much
Regards,
Flávio Justino
Try
using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "domain"))
{
using(UserPrincipal usr = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "username"))
{
usr.IsAccountLockedOut(); //Gets if account is locked out
}
}
You need to add dpendency System.DirectoryServices.AccountManagement.dll for the above code to work.
I have an intranet ASP.NET MVC3 web application that is using Windows authentication with .NET Framework 4. All my code is working as far as authenticating the users. I am using Windows Authentication for the baseline authentication, and then link the Active Directory user to a user in a table in SQL Server 2008 for additional user properties specific to my application. All of that is working fine.
There is a section of the site where admins can select Active Directory users to add to the SQL user table (see above) and put in their site specific properties (IsAdmin, ShoeSize, etc.). On this screen, there is a drop down list that I populate to retrieve all Active Directory from a custom object I created that just holds the username and full name properties of the Active Directory user. Here is this code for that:
public IQueryable<ActiveDirectoryUser> ActiveDirectoryUsers
{
get
{
// get list of users in the Active Directory
DirectoryEntry dirEntry = new DirectoryEntry("WinNT://" + Environment.UserDomainName);
List<DirectoryEntry> activeDirectoryUsers = dirEntry.Children.Cast<DirectoryEntry>()
.Where(c => c.SchemaClassName == "User").ToList();
// populate a custom class I have to hold the active directory user's username and full name property values
return activeDirectoryUsers
.Where(u => !string.IsNullOrEmpty(u.Properties["FullName"].Value.ToString()))
.Select(u => new ActiveDirectoryUser()
{
NetworkId = String.Format(#"{0}\{1}", Environment.UserDomainName, u.Properties["Name"].Value),
FullName = u.Properties["FullName"].Value.ToString()
}).AsQueryable();
}
}
For some reason, this code returns no results when the web application is deployed to IIS 7. However, this works perfectly when running the site from IIS Express in Visual Studio. Any ideas of why this would be happening? I have been looking for IIS settings as the culprit, but have not found anything helpful. Do I need to change the way I am retrieving the Active Directory users? Thank you!
This issue ended up being a combination of Eric J. answer, and a change to my code for getting the Active Directory entries. I found that the DirectoryEntry method can be overloaded to take a username and password to use for the permissions (e.g. you don't have to rely on whatever account IIS is running under. Here is the code:
List<SearchResult> searchResults;
// use login account to access active directory (otherwise it will use the IIS user account, which does not have permissions)
using (DirectoryEntry root = new DirectoryEntry("LDAP://CN=Users,DC=test,DC=example,DC=com", "usernameCredential", "passwordCredential"))
using (DirectorySearcher searcher = new DirectorySearcher(root, "(&(objectCategory=person)(objectClass=user))"))
using (SearchResultCollection results = searcher.FindAll())
{
searchResults = results.Cast<SearchResult>().ToList();
}
// get the active directory users name and username
return searchResults
.Select(u => new ActiveDirectoryUser()
{
NetworkId = String.Format(#"{0}\{1}", this._domainName, u.Properties["sAMAccountName"][0]),
FullName = (string) u.Properties["cn"][0]
}).AsQueryable();
This allowed me to get the Active Directory entries, but only those are Users and person objects. Then I used LINQ to map it to my custom model.
When running in IIS Express under Visual Studio you have a much higher permission set than running in the default security context of IIS 7.
You will have to understand exactly which permissions are needed to query Active Directory in this way and ensure that the application pool your app runs in under IIS 7 has that right. Be careful to grant only the permissions needed for this operation, and make sure you review the implications of granting those rights carefully before proceeding.
I am attempting to create a bug in TFS2010 by impersonating a user but always get
"TF30063 You are not authorized to access.."
I first authenticate using a service account and then attempt to impersonate a separate user account. I can successfully create Work Items using either account both programmatically and in the web UI. However, when I try to create the Work Item used an impersonated account (either way around) I always get this error. My code is:
public int Save(List<KeyValuePair<string, string>> values, ticketType type,string user)
{
// get the Uri to the project collection to use
Uri tfsuri = new Uri("http://94.23.12.119:8085/tfs");
// get a reference to the team project collection (authenticate as generic service account)
using (var tfs = new TfsTeamProjectCollection(tfsuri, new System.Net.NetworkCredential("username", "password", "servername")))
{
tfs.EnsureAuthenticated();
//Now get the details of the user we want to impersonate
TeamFoundationIdentity identity = GetImpersonatedIdentity(tfsuri,tfs,user);
//Now connect as the impersonated user
using (TfsTeamProjectCollection ImpersonatedTFS = new TfsTeamProjectCollection(tfsuri, identity.Descriptor))
{
ImpersonatedTFS.EnsureAuthenticated();
var workItemStore = GetWorkItemStore(ImpersonatedTFS);
// create a new work item
WorkItem wi = new WorkItem(GetWorkItemType(type, workItemStore));
{
//Values are supplied as a KVP - Field Name/Value
foreach (KeyValuePair<string,string> kvp in values)
{
if (wi.Fields.Contains(kvp.Key))
{
wi.Fields[kvp.Key].Value = kvp.Value;
}
}
ValidationResult = wi.Validate();
}
if (ValidationResult.Count == 0)
{
wi.Save();
return wi.Id;
}
else
{
return 0;
}
}
}
}
It successfully gets the impersonated identity but falls over on
ImpersonatedTFS.EnsureAuthenticated();
Both accounts have the 'Make requests on behalf of others' permission set.
First let me clarify one thing first. It seems your application is a server application, in which case there is no value in using EnsureAuthenticated(). It is just a performance tuning trick to help UI/desktop clients.
Now back to your main issue:
- If your application works as expected when you access locally but fails when you access remotely, then please read on, otherwise this is not the solution for you.
The reason it is failing is because the SPN needs to be added to the service account on the active directory. It is necessary for Kerberos authentication to take place.
This is something that TFS team needs to explain because many developers will forget about it while focusing at the job it hand. Hope this helps.
To learn more about SPN's and Kerberos fundamentals, check out these resources:
Kerberos for the busy admin.
Introduction to Kerberos SPN
I hope this helps.
Thanks!
Where do your users have the Make requests on behalf of others permission set? Is it at the Project Collection level (accessed via Team > Team Project Collection Settings > Security..) or at the TFS server level (accessed via Team Foundation Administration Console > Application Tier > Security..) ?
I think your problem is that you only have permission to impersonate at the 'Server' level, but you're trying to impersonate in a collection.
This is what Taylor has to say in his Introducing TFS Impersonation blog post:
This permission is encapsulated within each Team Project Collection
and within the Configuration Server. This means that if User A has
this permission on TPC1 he will not be allowed to impersonate users
when talking to TPC2 or the Configuration Server. Similarly, if User
B has this permission on the Configuration Server she will not be able
impersonate users when talking to any of the Team Project Collections.
I want to access some places on a remote machine.The folder i want to access have full control to EVERYONE. The code given below is used to access network path.
System.IO.DirectoryInfo locationInfo = new System.IO.DirectoryInfo(BackupLocationTxt.Text);
if (locationInfo.Exists)
{
// do some operations
}
The application run fine if both the host computer and the remote computer to be accessed having os windows xp .The application also run fine if the application is running inside visual studio .
Then my problems is ,any one of the machine( server and remote machine)having an os newer then windows xp( like windows 7, server 2008) locationInfo.Exists always false.
But if the application is running inside in visual studio, then it work fine independent of os
I searched a lot in net. But didnt find an exact solution yet. Someone suggests impersonation. But i dont know exactly how to do it. Is impersonations is the solution for my problem ?? Or is there any better ideas??
Any help will be greatly appreciated
You have an interesting problem, Null. How have you configured your sites Directory Security? If's Anonymous access is enabled, the folder open to Everyone may not be allowing access depending on the OS of the server (see this Microsoft KB Article for more information).
If the site is running as Anonymous, you could change the account that the site runs as in the IIS Manager, or you could enable Impersonation. When you are running the site in Visual Studio the site is running with your permissions, so Anonymous isn't a problem then.
You can use the following code to output the identity of the user that your site is running as to help figure out what is going on. You may be able to give the user your site run as access to the network location without any impersonation. Add a ASP:Label to you page and see who you are running as:
lblSomeLabel.Text = System.Security.Principal.WindowsIdentity.GetCurrent().Name
Impersonation could open you up to additional security risks, so you should do some more reading before making that change - but, the user you use for impersonation doesn't need to be a domain admin. In your case, the user may just need to have full access privileges to the network location.
You can read more about how to enable impersonation on this Microsoft KB Article. Below is some of the code from that page that I'd recommend. Rather than have your whole site run in impersonation mode, the code below runs only the part that you are having a problem with.
public void Page_Load(Object s, EventArgs e)
{
if(impersonateValidUser("username", "domain", "password"))
{
//Insert your code that runs under the security context of a specific user here.
undoImpersonation();
}
else
{
//Your impersonation failed. Therefore, include a fail-safe mechanism here.
}
}
private bool impersonateValidUser(String userName, String domain, String password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if(RevertToSelf())
{
if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if(token!= IntPtr.Zero)
CloseHandle(token);
if(tokenDuplicate!=IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
private void undoImpersonation()
{
impersonationContext.Undo();
}
Also, while serching for security articles I found this StackOverflow question that is worth a read.
Try System.IO.Directory.Exists instead.
Bear in mind that if you do not have at a minimum read-only permission to the directory, the Exists method will return false