4

I am developing an API using C# ASP.Net Core runtime and I'm planning to host this in IIS.

One of the requirement is to get information from another RESTful API server which currently has windows authentication (LDAP authentication).

I already have a solution by using a service account which is hardcoding the service account name and password in appsettings.json.

The code is as follows

var serviceApi = _config["Api:ServiceApi"].ToString(); // this is the URL of other RESTful API from appsettings.json
var serviceAccount = _config["ServiceAccount:UserName"].ToString(); // service account username from appsettings.json
var serviceAccountPwd = _config["ServiceAccount:Password"].ToString(); // service account password which is currently shown as clear text in appsettings.json
var serviceAccountDomain = _config["ServiceAccount:Domain"].ToString(); // service account domain name from appsettings.json
var client = new WebClient();
CredentialCache cc = new CredentialCache();
cc.Add(
    new Uri(serviceApi),
    "NTLM",
    new NetworkCredential(serviceAccount, serviceAccountPwd, serviceAccountDomain));
client.Credentials = cc;
client.Headers["Content-Type"] = "application/json";
string response = client.DownloadString($"{serviceApi}/User");

The downside of this solution is, the password of service account is visible in appsettings.json. I need other solution which will not expose the password in clear text.

One of the solution that I can think of is to store service account information in IIS application pool identity. However, I still cannot make WebClient to use IIS app pool identity. What I can do so far to make WebClient to use the NTLM credential of my own from windows.

Here's the code

var serviceApi = _config["Api:ServiceApi"].ToString();
var client = new WebClient();
client.UseDefaultCredentials = true; // this is not getting credential from IIS app pool identity but rather from logged in account in windows operating system
client.Headers["Content-Type"] = "application/json";
string response = client.DownloadString($"{serviceApi}/User");

Could please help me with how to use IIS app pool identity as credential for other RESTful API application?

Harish
  • 789
  • 1
  • 7
  • 21
ompusunggu
  • 41
  • 1
  • Can you try running the app in IIS with your app pool setup under a specific account? When run this way, there's no "logged in user" to speak of, unless you're running in IIS Express for development purposes, which runs under your account. – Madushan Apr 08 '21 at 04:05
  • Yes, I have tried IIS express and pure IIS (publish the application and host it in IIS), WebClient still doesn't pickup the IIS app pool identity. – ompusunggu Apr 08 '21 at 05:08
  • You have to check the [authentication](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/hh831496(v=ws.11)?redirectedfrom=MSDN#Impersonation) of the IIS WebSite, maybe you have Impersonation active? Do you need authentication on your website? Which? – Max Dec 02 '21 at 12:56
  • does this help ? https://stackoverflow.com/questions/12212116/how-to-get-httpclient-to-pass-credentials-along-with-the-request – iSR5 Dec 06 '21 at 00:19

2 Answers2

0

Ultimately we found we could not achieve this, as technically it compromises the security of the logged-in user unless you enable windows/NTLM auth on the API server (and this requires the browser/client to actively enable sharing the user's windows credentials with the server).

The solution we ended up using was using a pre-shared secret, in the form of an AppId and AppSecret, which seems to be the standard approach. Essentially we issued the calling application a username and password which exists outside of AD.

SSS
  • 4,807
  • 1
  • 23
  • 44
  • "and this requires the browser/client to actively enable sharing the user's windows credentials with the server" You clearly do not understand how NTLM GSSAPI or Kerberos SPNEGO works. – Aron Dec 07 '21 at 19:30
  • In no implementation of Windows Integrated Authentication do passwords get sent by the Browser to the WebServer. – Aron Dec 07 '21 at 19:35
0

Seems you have some misunderstanding about Windows Authentication.

  1. Windows Integrated Authentication is NOT LDAP authentication.
  2. LDAP is a wire protocol for querying data, similar to SQL, and lives on the same level on the OSI model as HTTP.
  3. WIA is designed to never allow the user's password to leave the Browser when used in HTTP (however NTLM is silly insecure as the LM hash is known to be broken).

So, given all the above. You want to use Windows Integrated Security with Kerberos SPNEGO between your frontend webserver and the backend webserver.

The following will be a short troubleshooting guide.

  • The backend server is identifying my service as [MachineName]. This is because you are using a non AD account to run your application. Use InProcess hosting and create a new AppPool with an AD service account to run the application.
  • The backend server is identifying my service as [Web Browser user]. This is highly unlikely to have happened by accident in a production environment. For this to occur, when the browser, the frontend, and the backend are all on different PCs, it must mean you accidentially turned on Windows Auth, Windows Impersonation, Kerberos Authentication, and set up SPNs for Delegation between frontend and the backend. All without making a mistake. I've spent months of my life trying to do this on purpose.
  • The Powers that Be mandated that we disable NTLM auth and Kerberos isn't working. Most likely your problem is setting up SPNs on your AD for the http address to point to your AppPool Identity (which again must be an AD account or the machine account).
Aron
  • 15,464
  • 3
  • 31
  • 64