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();
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'm developing an application that requires me to install a Windows Service as a user (so far, I was registering successfully it as LocalSystem, but the requirements had changed).
I'm aware that, if I set ServiceAccount as User, it would prompt me with the credentials. That's ok for me. But when I hit ok, it gives me an error saying username or password are wrong, even after I triple-check it.
I can only "bypass" it by changing the Log On property AFTER I've installed the Windows Service, which is not ideal. Am I wrong about something? Here's the snippet of code I'm trying to use.
process = new ServiceProcessInstaller();
process.Account = ServiceAccount.User; //.LocalSystem works fine.
service = new ServiceInstaller();
service.ServiceName = "myService";
service.StartType = ServiceStartMode.Automatic;
Installers.Add(process);
Installers.Add(service);
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 am trying to access a WCF service (MS CRM 2011) and getting the above error. If I run my sample program from the VS2010 debugger with either Cassini or IIS Express it works great. No authentication errors.
However, if I publish the site to my local IIS 7.5 (running Windows 7 64 bit), I get the error on the line that grabs the CRM UserId (WhoAmIResponse).
I opened Fiddler to compare the requests between running under the debugger and running under IIS. On the site running under IIS the request never even comes across, so it must be failing before getting that far.
The site as published to IIS has its web.config set for ...
<authentication mode="Windows">
</authentication>
<identity impersonate="true"/>
The site is running under the preinstalled ASP.NET v4.0 app pool, Integrated pipeline mode, ApplicationPoolIdentity account.
Here is my code...
public class DemoController : Controller
{
public ActionResult Index()
{
ClientCredentials credentials = new ClientCredentials();
credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
var _serviceProxy = new OrganizationServiceProxy(new Uri("http://svr-rex2011-dev/TimeEntry/XRMServices/2011/Organization.svc"),
null,
credentials,
null);
// This statement is required to enable early-bound type support.
_serviceProxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());
IOrganizationService service = (IOrganizationService)_serviceProxy;
// Display information about the logged on user.
Guid userid = ((WhoAmIResponse)service.Execute(new WhoAmIRequest())).UserId;
SystemUser systemUser = (SystemUser)service.Retrieve("systemuser", userid,
new ColumnSet(new string[] { "firstname", "lastname" }));
// Retrieve the version of Microsoft Dynamics CRM.
RetrieveVersionRequest versionRequest = new RetrieveVersionRequest();
RetrieveVersionResponse versionResponse =
(RetrieveVersionResponse)service.Execute(versionRequest);
ViewBag.FirstName = systemUser.FirstName;
ViewBag.LastName = systemUser.LastName;
ViewBag.Version = versionResponse.Version;
return View();
}
}
Any ideas? Much appreciated!!!
It seems the situation you are describing is this: you are getting authentication errors when your app tries to access the CRM service when it is running on IIS. When you run your app from Visual Studio or IIS Express then you don't have authentication errors.
If this is true, I'm pretty sure your issue is due to the identity used to run the IIS AppPool for your application. You need to change the AppPool identity to one that has network access to the CRM service. Normally it should be a domain account with the correct permissions but there are ways of doing this using local machine accounts that have the same password (definitely not recommend if a domain is available).
I was having the same problem and, in my case, it turned out to be due to the fact that CRM was load-balanced. It turns out that Authentication delegation through Kerberos does not work in load-balanced architectures.
We got around this by pointing our application directly to one of the CRM servers via a HOST entry, which bypassed the load balancing.
I hope that saves someone the several hours it cost me.
We have a program that uses webdav, authenticating with windows authentication so users don't have to type their username and password. this worked fine until we migrated domain. now the code that used to connect returns error code 5 (access denied):
string psPassword =null, psUsername=null;
structNetResource stNetRes = new structNetResource();
stNetRes.iScope = 2;
stNetRes.iType = RESOURCETYPE_DISK;
stNetRes.iDisplayType = 3;
stNetRes.iUsage = 1;
stNetRes.sRemoteName = WebDAVServerpath;
stNetRes.sLocalName = null; //connect, but don't show drive in my computer
int iFlags = CONNECT_CMD_SAVECRED;
int i = WNetAddConnection2A(ref stNetRes, psPassword, psUsername, iFlags);
Does anyone have any idea how to fix this? I've tried running
int j = WNetCancelConnection2A(WebDAVServerpath, CONNECT_UPDATE_PROFILE, 0);
beforehand to clear any old connections but this isn't working.
(Running net use \\server.domain.com\share now prompts for a username and password whereas before it used to connect straight away, so it looks like something's interring with windows authentication.)
Edit - This is a WinForms application, IIS and the shared files are stored on the same machine. The problem only occurs on machines that were migrated; PCs that were (and still are) outisde our domain are unaffected.
If your file server and web server are not the same machine, you need to set up the file server to trust the web server for delegation. This allows the file server to trust the credentials that the web server has authenticated instead of re-prompting for credentials on each request.