When executing the following c# code impersonating a user I have an exception (I do not have details on the exception):
public static void CheckIIS()
{
// list al websites on IIS
DirectoryEntry w3svc = new DirectoryEntry("IIS://localhost/W3SVC");
foreach (DirectoryEntry ws in w3svc.Children)
{
if (ws.SchemaClassName != "IIsWebServer")
continue;
//
// Website found!
}
}
Which roles the windows user must have to avoid exceptions?
Thanks.
I guess your exception is "Access denied". This is a common issue when using impersonation authentication.
You can try set this impersonation user being a member of IIS_IUSRS group. It solves the similar problem.
Related
Please check the following code.
WindowsIdentity identity = HttpContext.Current.Request.LogonUserIdentity;
WindowsPrincipal principal = new WindowsPrincipal(identity);
bool result = Principal.IsInRole("Active Directory Group Name");
if(result == true)
{
// Able to access the page
}
else
{
// No access to this page
}
I have a pin in my organization and it is added to "Active Directory Group". Now, I am able to access the pages in the localhost. I made some changes in the code and deployed code in DEV and trying to access the pages in DEV to test the application. In DEV, I was unable to access the pages. It is supposed to execute the if block but instead executes the else block.
Could you please help me with:
Where is security blocking me?
What else do I have to make sure of?
I am developing an MVC app and I would like to auto login users into the system by retrieving their email address from Active Directory, use that email address to find a user in my database, if found log them into the system. The Idea is for the system to not force the user to input login details after already logging into their workstation that is setup on a work domain/Active Directory.
Please help me with pointers on this as I've tried most approaches described in many threads.
I've set my IIS app pool to Network Service
ASP.NET Impersonation is disabled..
I've enabled Load User Profile in app pool -> Advanced Settings
When I use the code below, the search fails:
using ( System.Web.Hosting.HostingEnvironment.Impersonate() )
{
PrincipalContext ctx = new PrincipalContext( ContextType.Domain );
UserPrincipal user = UserPrincipal.FindByIdentity( ctx, User.Identity.Name );
Response.Write( "User: " + User.Identity.Name );
Response.Write( user.EmailAddress );
Response.Flush();
Response.End();
}
Error: The (&(objectCategory=user)(objectClass=user)(|(userPrincipalName=)(distinguishedName=)(name=))) search filter is invalid.
Can someone please point me into the right direction of what I am trying to achieve? Am I approaching my requirement wrongly?
Thanks in advance.
For users to be logged in automatically, you need to use Windows Authentication. For that to work, there are a few prerequisites:
The users must be logged into Windows with the account they will use to authenticate to your website.
Your website must be added to the Trusted Sites in Internet Options in Windows (or considered an "Intranet Site") so that IE and Chrome will automatically send the credentials. Firefox has its own setting called network.negotiate-auth.trusted-uris.
Your server must be joined to a domain with a trust to the domain of the users (usually it's the same domain).
If all those things are true, then you can follow the instructions here to install the Windows Authentication feature in IIS (depending on your version). If you're using IIS Express for running it locally, then you can skip this step on your development machine.
Then enable the use of Windows Authentication in your website by modifying your web.config file. Add this under the <system.web> tag:
<authentication mode="Windows" />
And add this under <system.webServer>:
<security>
<authentication>
<windowsAuthentication enabled="true" />
<anonymousAuthentication enabled="false" />
</authentication>
</security>
Then, as long as your website is trusted by the browser (step 2 above), you will automatically be logged in. The username of the logged on user will be User.Identity.Name. All of the code you show will work, however you don't need to call System.Web.Hosting.HostingEnvironment.Impersonate().
public bool CheckUserInGroup(string group)
{
string serverName = ConfigurationManager.AppSettings["ADServer"];
string userName = ConfigurationManager.AppSettings["ADUserName"];
string password = ConfigurationManager.AppSettings["ADPassword"];
bool result = false;
SecureString securePwd = null;
if (password != null)
{
securePwd = new SecureString();
foreach (char chr in password.ToCharArray())
{
securePwd.AppendChar(chr);
}
}
try
{
ActiveDirectory adConnectGroup = new ActiveDirectory(serverName, userName, securePwd);
SearchResultEntry groupResult = adConnectGroup.GetEntryByCommonName(group);
Group grp = new Group(adConnectGroup, groupResult);
SecurityPrincipal userPrincipal = grp.Members.Find(sp => sp.SAMAccountName.ToLower() == User.Identity.Name.ToLower());
if (userPrincipal != null)
{
result = true;
}
}
catch
{
result = false;
}
return result;
}
I believe there are many ways on how we can retrieve AD users from C# MVC. http://www.codedigest.com/posts/5/get-user-details-from-active-directory-in-aspnet-mvc please take a look at this good example using the galactic API(free and open source package).
I have a SharePoint solution with a custom application where a user should be able to change some properties in his own Active Directory object.
I am doing the following:
PrincipalContext ctx = ActiveDirectory.GetPrincipalContext("lab");
UserPrincipal user = ActiveDirectory.GetUserPrincipal(ctx, "Administrator");
user.DisplayName = user.DisplayName + DateTime.Now.ToString("ddMMyyyyHHmmss");
user.Save();
I am logged in to SharePoint as the domain administrator and i am trying to change my own DisplayName.
What is wrong with my code?
Update 20.04.2016
I have built a small Console Application with the following code:
static void Main(string[] args)
{
try
{
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "lab");
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "administrator");
DirectoryEntry de = (user.GetUnderlyingObject() as DirectoryEntry);
user.DisplayName = user.DisplayName + DateTime.Now.ToString("ddMMyyyyHHmmss");
user.Save();
Console.WriteLine("OK");
Console.ReadKey();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
This works fine! That means normally, that the Authentication goes wrong or the user which is logged into SharePoint is not getting used to connect to AD and do the changes. If this could be the case, how could i find out with which user i am doing the operation?
Update 20.04.2016 - 2
I have now tried to put the username and password in the PrincipalContext contructor as below:
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "lab", "administrator", "pass");
This works, too! That means now definitely, that the user which is logged in to SharePoint is not used to create the PrincipalContext. But why? Normally code is always executed in the context of the current user!?
How can i find out which user is used to create the PrincipalContext and how can i change it that the logged in user is getting used?
I had the same problem, I resolved it like this:
In IIS, in the advanced settings of my app -> In Identity I add my service account (example: domain\service-account)
In my active directory, I give to this service account full control on folder and sub-folder where I want to create/update user (you need to modify view to see security tab -> right click -> view -> advanced features)
If you already have that, check if your service account is not disabled
And now everything is working :)
I have an asp.net application that uses delegation to perform actions on the Active Directory as the authenticating user. The application works perfectly on some computers and doesn't work at all on other computers, on these other computers they receive a COMexception error code 0x80072020 the stack trace is:
System.Runtime.InteropServices.COMException (0x80072020): An operations error occurred.
at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
at System.DirectoryServices.DirectoryEntry.Bind()
at System.DirectoryServices.DirectoryEntry.get_AdsObject()
at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
at System.DirectoryServices.DirectorySearcher.FineOne()
at ResetUnlockAccount.ResetUnlockAccount.ExecuteImpersonation(String username)
The code that is throwing the error is:
WindowsIdentity winId = (WindowsIdentity)HttpContext.Current.User.Identity;
WindowsImpersonationContext ctx = null;
try
{
ctx=winId.Impersonate();
using (DirectoryEntry directoryObject = new DirectoryEntry(ROOT))
{
using (DirectorySearcher search = new DirectorySearcher(directoryObject))
{
search.Filter = "(&(objectClass=user)(SAMAccountName=username))";
search.SearchScope = SearchScope.Subtree;
///////////////////////////////////////////////////////////////////
This line is causing the issue.
---------->SearchResult result = search.FindOne();
using (DirectoryEntry user = result.GetDirectoryEntry())
{
user.Invoke("SetPassword", new object[] { password });
user.Properties["pwdLastSet"][0] = 0;
user.CommitChanges();
lblOutput.Text = "It worked";
}
}
}
}
catch (Exception ex)
{
lblOutput.Text += ex.ToString();
}
finally
{
if (ctx != null)
ctx.Undo();
}
At first I thought it was a User permission issue, so I tested it by trying my credentials on one of the computers that was having issues, I encountered the same issues. To confirm it wasn't User permission issues I tried it on my workstation with the other persons credentials and it worked perfectly.
I wrote a quick test program that would show me the impersonation level of the users, when working correctly it should be Delegation. When I ran it on my machine the output was:
Authentication Type: Negotiate
Token: 9999
Name: domain\username
Is Authenticated: True
Impersonation level: Delegation
When I ran it on the other Workstation:
Authentication Type: Negotiate
Token: 9999
Name: domain\username
Is Authenticated: True
Impersonation level: Impersonation
Server: IIS 7.0
Browser: IE 8
I don't know what is causing the issue with only certain computers, if anyone knows of a specific setting that should be changed for delegation to work properly I would be grateful. Below I have posted two other links that will help give more insight into my problem.
.GetDirectoryEntry throws COM exception, code:0x800720720 when attempting to bind to object
asp.net application userprincipal.findbyidentity works with browser on server, throws exception from my machine
I'm creating a PrincipalContext object for retrieving a user's groups from our AD database (we use these then for authentication to various parts of the site).
This used to be done using forms authentication, so the code looked something like this
PrincipalContext pc =
new PrincipalContext(ContextType.Domain, "domain.com", username, password);
UserPrincipal usp =
UserPrincipal.FindByIdentity(pc, IdentityType.Guid, user.Guid.ToString());
foreach (var group in usp.GetGroups())
{
// Add group to collection
}
However, we recently switched to windows authentication, and I no longer have access to the user's password.
How can I search the AD database using the current user's credentials? I've tried using impersonation, but it throws an An operations error occurred error on the FindByIdentity line. If I forget about authentication all together I'm limited in the number of groups that are returned.
Here is a method I use, You could change it to return a collection:
public static List<string> getGrps(string userName)
{
List<string> grps = new List<string>();
try
{
var currentUser = UserPrincipal.Current;
RevertToSelf();
PrincipalSearchResult<Principal> groups = currentUser.GetGroups();
IEnumerable<string> groupNames = groups.Select(x => x.SamAccountName);
foreach (var name in groupNames)
{
grps.Add(name.ToString());
}
return grps;
}
catch (Exception ex)
{
// Logging
}
}
I assume you want the results IEnumerable, which is what I did here.
Anon's answer works for what I asked, but I also wanted to be able to search for other user's groups. The best way I've found to do this is to run the asp.net program's app pool under a service account, and then use my original code.
To do this in IIS Manager 7.5, go to the Application Pools, right click on the one your app is running under -> Advanced Settings, and change the identity from "ApplicationPoolIdentity" to a custom domain account.