I have written the code as below:
try
{
ClientContext context = new ClientContext("https://test.com/");
System.Net.ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) => true);
string strUserName = #"abc";
string strPassword = "pwd";
var credentials = new NetworkCredential(strUserName, strPassword);
Web web = context.Web;
context.Load(web, w => w.Title);
context.Credentials = credentials;
context.ExecuteQuery();
// Now, the web's properties are available and we could display
// web properties, such as title.
System.Console.WriteLine("Web Title");
System.Console.WriteLine(web.Title);
}
catch (Exception ex)
{
}
It's working fine in the console application, but same code is not working when I am calling from a web service.
Given our discussion; the problem is likely that the account that your IIS app pool is running under is not authorized to access the Sharepoint site. You need the app pool account to have access in AD in order for your code to work. You'll need to do one of the following;
Get the App pool account granted AD rights to Sharepoint. This is less likely as IIS 7 and above use "odd accounts" by default for app pools.
More likely is you'll need to change the account your app pool is running under to one that has the appropriate AD rights. In most companies I've worked for there is a "Service Account" or "Automated Account" used for this purpose.
Related
I have a .net core application that is hosted on IIS. This application utilizes System.Management to connect to other machines to gather information.
I am noticing that some of my calls are getting an access denied response. The application pool is running as a user that is an admin on the remote machines. However the ManagementScope does not appear to be using the Application pool's identity.
I was wondering if there is a way to use the WindowsIdentity while connecting to the remote machine?
I am looking for something like the following.
private ManagementScope GetManagementScope(string machineName)
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
ConnectionOptions options = new ConnectionOptions
{
Impersonation = ImpersonationLevel.Impersonate,
Username = identity.Name
// Something here to pass along the password?
};
ManagementPath path = new ManagementPath
{
Server = machineName,
NamespacePath = "\\root\\MicrosoftIISv2"
};
return new ManagementScope(path, options);
}
I have tried hard coding the User name and password and that works fine but I would really like to use the Application pools identity.
I think, and hope, there is no way to retrieve the password.
The only way is to pass it as external parameter and possibly stored in a secure application.
Maybe you can consider to store this secret in Azure Key Vault and retrieve that setting.
I have ASP.Net application which uses TFS API and works under Domain. The problem is that locally everything works fine. After deployment to IIS, which is configured to use ApplicationPoolIdentity, my app is giving me 500 Internal Server Error. When I set Identity to use my username and password everything works fine again. App uses Windows authentication, and is used by multiple users.
We're submitting data to TFS, and if Identity is configured to my username, the in TFS history it shows that I have modified that item. We need it to be the user that actually made the modification.
Before in some places, like "Assigned To" or "Deployed By" I used
var currentDisplayName = System.DirectoryServices.AccountManagement.UserPrincipal.Current.DisplayName;
After I discovered this issue, resolved it by using
var currentDisplayName = System.Web.HttpContext.Current.User.Identity.Name;
But the issue where when i use Identity - ApplicationPoolIdentity, the app is not working.
Method where i get Team Project Collection:
var tfsTeamProjectUrl = ConfigurationProvider.TfsTeamProjectUrl;
var teamProjectCollection = new TfsTeamProjectCollection(new Uri(tfsTeamProjectUrl));
teamProjectCollection.EnsureAuthenticated();
return teamProjectCollection;
Locally this works fine, but on IIS, it wants to use Identity from IIS App Pools, But i need it to use credentials from the actual user.
UPDATE
I tried to Impersonate the actual user by doing this:
var tfsTeamProjectUrl = ConfigurationProvider.TfsTeamProjectUrl;
var baseUserConnection = new TfsTeamProjectCollection(new Uri(tfsTeamProjectUrl));
var ims = baseUserConnection.GetService<IIdentityManagementService>();
var username = System.Web.HttpContext.Current.User.Identity.Name;
var identity = ims.ReadIdentity(IdentitySearchFactor.AccountName, username,
MembershipQuery.None, ReadIdentityOptions.None);
var teamProjectCollection = new TfsTeamProjectCollection(new Uri(tfsTeamProjectUrl), identity.Descriptor);
teamProjectCollection.EnsureAuthenticated();
return teamProjectCollection;
But now i'm gettin
An exception of type 'Microsoft.TeamFoundation.TeamFoundationServerInvalidResponseException' occurred in Microsoft.TeamFoundation.Client.dll but was not handled in user code
Additional information: Please contact your administrator. There was an error contacting the server.
Technical information (for administrator):
HTTP code 500: Internal Server Error
It seems like IIS is deciding to try to access TFS with the app pool identity instead of the credentials that you are explicitly supplying. You are authenticating to the server but then not using the server object, so the app was reverting to whatever identity it was running under.
Try to use the authentication with below code:
string tfsServerUrl = "http://servername:8080/tfs";
System.Net.NetworkCredential tfsCredential = new System.Net.NetworkCredential("ServiceAccountName", "password", "DOMAIN");
TfsConfigurationServer tfs = new TfsConfigurationServer(new Uri(tfsServerUrl), tfsCredential);
tfs.Authenticate();
I want to create a service which to crawl all inboxes of all users on a hosted exchange server (“myclient.onmicrosoft.com”) via EWS.
This already works well when I connect to on-premise exchange servers in the same domain. But when I try to connect this service to a hosted exchange, it throws 401 (wrong authorization) errors. Of course, this is a different domain as the hosted exchange server.
My service runs on an on-premise server and uses a “god-mode” user to impersonalise to all active directory users. My question is: How to connect the users of my on-premise system correctly to the hosted exchange in a different domain?
Note: It works when I use the credentials directly and the impersonation way does work on on-premise installations.
What I did so far (and I wonder of this is the right way to do it): On our on-premise server I created a domain “myclient.onmicrosoft.com” just like on the hosted server and an AD user with the same name and password as on the hosted exchange (called “mytest#myclient.onmicrosoft.com”).
On my crawler service I did:
I got all AD users in our on premise server
var allUsers = SearchAllActiveDirectoryUsers();
foreach (DataRow user in allUsers.Rows)
{
String domainName = (String)user["DomainName"];
String samAccountName = (String)user["SamAccountName"];
String principalName = (String)user["PrincipalName"];
String principalDomainName = (String)user["PrincipalDomainName"];
String mail = (String)user["Mail"];
}
Then for each AD user I connected the user with the exchange service like this:
ExchangeService ex = new ExchangeService(version);
ex.Url = new Uri(“https://outlook.office365.com/EWS/Exchange.asmx”);
ex.Credentials = new WebCredentials("mytest#myclient.onmicrosoft.com", “XXX”, " myclient.onmicrosoft.com");
// THIS DOES WORK CORRECTLY!
ex.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, “mytest#myclient.onmicrosoft.com”);
//this does NOT work!
Any ideas what I am missing?
You need to use the credentials of your "god-mode" user, but set the ImpersonatedUserId to the AD user. Something like:
ex.Credentials = new WebCredentials("account_with_impersonation_rights#myclient.onmicrosoft.com", "password");
ex.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, "mytest#myclient.onmicrosoft.com");
When you connect to Office 365 via EWS, you always need to supply credentials. You can't use UseDefaultCredentials = true.
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.
I would like to run a process from an intranet client on the WCF service side. In my case a client asks a server to create a new process on the server's machine under the provided credentials. WCF service is hosted on IIS 7.5 and I start a process using this code
var processInfo = new ProcessStartInfo("C:\\Windows\\System32\\notepad.exe")
{
UserName = "some user",
Password = MakeSecureString("some password"),
UseShellExecute = false,
LoadUserProfile = true
};
Process process = Process.Start(processInfo);
This code works if I host WCF service as a self-hosted console application running under admin user and I see the notepad started under another user. It fails on IIS with no exception, but process is immediately terminated
process.HasExited = true;
process.ExitCode = -1073741502;
On IIS WCF application is running under the user with admin rights and has got full trust defined in web.config. I cannot use self hosted application as it doesn't support easy continuous delivery (like WebDeploy with IIS web farms).
Q: How can I start a process on a server side from WCF service hosted on IIS?
EDIT:
I stumbled upon this post, with similar issues and I tried all the methods there, including all possible variations for Process.Start and P/Invoke with CreateProcessWithLogonW and CreateProcessAsUser I also tried granting additional permissions to users. Non of this would work with the error messages identical to the ones the guy had posted.
Oleksii, the point is that if you host the WCF service in a console application, there is a windows session (a user logged in and Windows Explorer loaded) for that user and the notepad is opened and shown for that user, so you see it in the UI.
when you host your WCF service in IIS, being a server, IIS requires and allows no user interaction and works also if no user is logged in; in that context there is no UI to host your notepad or other UI enabled applications, you could execute a process for elaboration or other batch jobs but not render a windows UI application, because Windows Explorer is not loaded for you and there is no place to render your process's UI.
here is what I use to call GnuPGP to do encryption. How does your setup compare?
private int ExecuteCommand(string arguments, string passPhrase, int timeout)
{
Process processObject;
ProcessStartInfo pInfo = new ProcessStartInfo(_executablePath, arguments);
pInfo.CreateNoWindow = true;
pInfo.UseShellExecute = false;
pInfo.RedirectStandardInput = true;
pInfo.RedirectStandardOutput = true;
pInfo.RedirectStandardError = true;
processObject = Process.Start(pInfo);
if (!string.IsNullOrEmpty(passPhrase))
{
processObject.StandardInput.WriteLine(passPhrase);
processObject.StandardInput.Flush();
}
string result = processObject.StandardOutput.ReadToEnd();
string error = processObject.StandardError.ReadToEnd();
if (!processObject.WaitForExit(timeout))
{
throw new TimeoutException("GnuPG operation timeout. Waited " + timeout + " milliseconds ");
}
int exitcode = processObject.ExitCode;
Error = error;
Output = result;
return exitcode;
}
There's an apppool setting to make sure it loads the user profile.
loadUserProfile Optional Boolean attribute.
Specifies whether IIS loads the user profile for the application pool identity. Setting
this value to false causes IIS to revert to IIS 6.0 behavior. IIS 6.0 does not load the
user profile for an application pool identity.
The default value is false.
That along with being a domain user as the identity with enough permissions might work?? I know that at a minimum the user will need a user profile.
That said, it's a little bit of an odd architecture. It seems like a better arch would be to have a persistent process like a windows service that the site communicates with but I'm not sure what your constraints are.
Hope that helps.