Saving to Active Directory - Access Is Denied for Domain Admin - c#

I'm working on a C# Web Application to allow read and write access to Active Directory user accounts.
I have got this working great on our main company AD- I can read accounts, get attributes, save details back to AD, enable/disable accounts etc. I'm using impersonation to do this, so just before it saves to AD it changes to using a different account (which belongs to Domain Admins), then reverts to the main app pool account after saving.
I've just been given the requirement to add user accounts through the app, but I'm not happy about testing this on the main AD, and I've therefore setup a VM with a test AD. I've got the app setup on that VM, and it reads from AD fine. I've setup the same user account that I impersonate on the live AD, and have added it to the domain admins group. However, when I try to save details to an existing user I get an "Access is Denied" error.
I know the impersonation is working as just before saving I output the result, and I tried changing the password and it failed with a different error.
I've asked our Network Administrator if he's setup anything special on the impersonation user for the live AD, but he says he hasn't, and they appear to be identical.
Does anyone know of anything else I might need to do other than add the impersonation user to the domain admins group? I've tried logging into the VM as the user, and have made a change to a user account through AD itself, so the user does seem to have the required level of access.
The following is the code I'm using to impersonate the user:
Impersonation imp = new Impersonation();
string impResult = "";
imp.ImpersonateDomainUser(out impResult, ConfigurationManager.AppSettings["ADAdminUserLogin"], user.Domain, ConfigurationManager.AppSettings["ADAdminUserPwd"]);
...
imp.Revert();
impResult returns the following:
Before impersonation: NT AUTHORITY\SYSTEM
After impersonation: TESTDOMAIN\user.manager.service
The code I'm using to save to AD is:
var entry = new DirectoryEntry();
var account = userName.Replace(domain, "");
var search = new DirectorySearcher(entry) { Filter = "(SAMAccountName=" + account + ")" };
search.PropertiesToLoad.Add(propertyName);
var result = search.FindOne();
if (result != null)
{
DirectoryEntry entryToUpdate = result.GetDirectoryEntry();
if (propertyValue == null || propertyValue.ToString().Length == 0)
entryToUpdate.Properties[propertyName].Clear();
else
entryToUpdate.Properties[propertyName].Value = propertyValue;
entryToUpdate.CommitChanges();
entryToUpdate.Close();
entryToUpdate.Dispose();
}
Any advice would be much appreciated.

This issue was down to User Access Control settings on the Virtual Machine.
Once I disabled User Access Control through the control panel, I was then able to save users to Active Directory. Its possible that running the browser as administrator may have also worked, though I didn't try this.

Related

WPF application with Windows authentication

I have a simple wpf client (few text boxes) that uploads some data to a web service. And I want to use windows authentication to go with my application.
I am checking in OnStartup of App.xaml, whether or not the user is authenticated. My question is around what is the meaning of Thread.CurrentPrincipal.Identity.IsAuthenticated.
I don't want my application to be used from outside my network as it is connecting to a web service and uploads data. But my assumption is as long as you run this application from inside any windows network the above mentioned property will always return true?
So how do I find out if the application is being run from inside my network. I don't think checking domain name or role name is any different, because I can always setup a domain and name it whatever I want. I don't want to prompt user for username or password of any sort.
How do you check Identity of user against a particular AD (AD might not be publically available). Basically the application should only works from my local network or through VPN.
var context = new PrincipalContext(ContextType.Domain, "DOMAINNAME");
var result = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName);
If the result is null, then the user does not exists in the AD domain.
You can also user DirectorySearcher class to query AD based on a filter criteria. This is more useful only if you would like to retrieve additional details about the user like contact, email address etc.

LDAP and ActiveDirectory authentication in C#

I am new to LDAP and active directory authentication , I just studied few things about LDAp authentication and done with sample application
I just checking Does the user exist in ActiveDirectory or not
public static bool DoesUserExist()
{
using (var domainContext = new PrincipalContext(ContextType.Domain,Environment.UserDomainName))
{
using (var foundUser = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, Environment.UserName))
{
return foundUser != null;
}
}
}
in our local system its working fine , But when i hosted in ActiveDirectory Server and i am trying to access this with server IP address, i am facing some issue like
ContextType.Domain,Environment.UserDomainName and Environment.UserName
for these three values are coming from server Information not the users who accessing this application
So please help me how to get the User information(who accessing this application) so that i need to pass those info to server and need check for user is activedirectory user or not
Environment.UserDomainName returns the domain part of Environment.UserName, e.g. "mydomain.com", so you don't want that.
Environment.UserName itself will return the user who is currently "logged in to Windows", i.e. the app pool user - see MSDN.
You are better off checking the identity of the current web request, so in a MVC Controller or WebForms Page, use this.User.
Or if you are using Windows Authentication or hooking Forms Authentication into AD, the current Thread Principal should be the current request user, so you can use Thread.CurrentPrincipal.Identity.

Log AD users in

I have a login form written in C# and I want only AD users to be able to login.
How should I do this?
string UserName = "";
string Pass = "";
Although it is not an ASP.Net app the active directory membership provider will work just fine.
Here is info on how to use this library:
http://msdn.microsoft.com/en-us/library/system.web.security.activedirectorymembershipprovider.aspx
and here is some more information:
http://msdn.microsoft.com/en-us/library/ff650308.aspx
I am sure that this is not a best practice, but, depending on your security needs, you could allow all domain users and exclude local users by checking just the UserDomainName in the Form_Load. This simple approach piggybacks on their computer login, and does not have the complexity of any LDAP/AD calls.
if (SystemInformation.UserDomainName.ToString() == "myDomain")
{
// your normal form load code here
}
else
{
form1.Close(); //this is a simple but effective to pull the rug out from
//under them if they do not have the permissions
//TODO email the application administrator the `SystemInformation.UserName` of the user who was not given permissions
}
In my environment, since our in-house apps are deployed via ClickOnce (installed per user per computer), a similar approach (we compare usernames too) has always been sufficient for us.
If you want to know how to verify credentials to Active Directory in order to allow AD users in you application, you should check this.
You'll find how to verify the content of your textboxes and verify if username and passowrd matches (directly with the AD).

Get system logged in username in c# that also works in IIS

I thought its simple to get the logged in username, in fact, it works fine with most of the responses available on stack overflow but when I publish the website all method fails.
Can anybody please guide me to get the name of the logged in user from Windows with following condition.
I just need logged in user name so forget about AD when you write the response.
I cannot change to Windows authentication mode because user may be a guest user who is not part of company but still have access to my intranet website
it’s not possible to change the user browser setting as there are more than 6000 users
I cannot disable the anonymous authentication as I want everyone to be able to use the website
I have already tried following solution and all works fine when I run the website on debug mode but all fails to return the username when I publish the website on IIS so please help me with some new as solution
string _windowLogonUserName = System.Environment.UserName.ToString()
string _windowLogonUserName =
WindowsIdentity.GetCurrent().Name.Remove(0, _adDomainName.Length + 1)
string _windowLogonUserName =
System.Web.HttpContext.Current.User.Identity.Name.ToString();
System.Security.Principal.WindowsIdentity.GetCurrent().Name;
AppDomain appDomain = Thread.GetDomain();
appDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
WindowsPrincipal windowsPrincipal = (WindowsPrincipal)Thread.CurrentPrincipal;
Logger.Write("username principal" + windowsPrincipal.Identity.Name);
Request.ServerVariables["LOGON_USER"]
It sounds like you're publishing the site outside of the AD domain. if the server is not on the domain, it won't be able to authenticate (or even accept) Windows users. The basic answer is that you can't get it.
If the server is internal (on the domain) then you can enabled integrated windows auth in IIS. Here's a reference.

How to search Active Directory when dialed in remotely?

Is there a way to use a credential coming from the user's saved password list and use that instead of the local Windows credentials?
I need to look up a user's email address based on their Active Directory username to allow them to register for email updates via an intranet site. This seems easy enough if the user is actually logged into a machine directly that's part of the domain - I can use their identity name to search the AD based on their username:
using( DirectoryEntry root = new DirectoryEntry("LDAP://admachine.domain.local") )
{
using( DirectorySearcher searcher = new DirectorySearcher(root) )
{
// strip the domain from the username and find the user in AD
var username = Regex.Replace(Page.User.Identity.Name, #".*\\", string.Empty);
searcher.ReferralChasing = ReferralChasingOption.All;
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = string.Format("(&(objectCategory=user)(objectClass=person)(sAMAccountName={0}))", username);
var foundUser = searcher.FindOne();
// error checking occurs here...
var email = foundUser.Properties["mail"][0].ToString();
// TODO: stuff with the email address
}
}
However, if working from a PC at home this doesn't work. Page.Identity.Name resolves to the name I'm logged onto my own PC (MyMachine\Dave), ignoring stored credentials I used to authenticate with my work domain (WorkDomain\dave.downs).
The DirectoryEntry picks up and uses the saved credential just fine, allowing me to actually bind to and search the AD, but I can't find a way of then using it as the var username, which will contain of my local machine username instead.
Is there a way to actually do what I'm trying to do, or am I just going about things the wrong way/hitting my head against a brick wall?
I assume you are using IIS. Disable Anonymous Access and enable windows authentication. That way anybody who is not in the domain will get a popup that allows them to specify their domain user and password. For users that are coming from a domain enabled server nothing changes. But that way you guarantee that the identity will always resolve to a valide domain user. So this should solve your "I am seeing a non-domain user" problem. Check Windows Authentication Provider for details.
If they are logged in via Windows Auth, you can use:
System.Security.Principal.WindowsIdentity.GetCurrent().User
which will give you the sid of the logged in user.
Disable anonymous access and integrated security in IIS, force them to log in via basic auth under https. This will give make sure the the current session is running under an authenticated domain user.

Categories

Resources