Reputation: 1504
I am running an ASP.NET Core application hosted in a Windows service as described here:
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service?view=aspnetcore-2.1
I need this application to support Windows Authentication. What are my options? I tried using Application Request Routing / URL Rewrite module in IIS as a reverse proxy with Windows Authentication but could not figure out how to make that work. Any guidance would be appreciated.
Upvotes: 22
Views: 31648
Reputation: 40948
Microsoft has a whole article about Windows Authentication in ASP.NET Core, including a section describing how to do it without IIS. Kestrel doesn't support Windows Authentication (Update: it does now), so you have to host with HTTP.sys. It looks easy at first (in your Program.cs):
.UseHttpSys(options =>
{
options.Authentication.Schemes =
AuthenticationSchemes.NTLM | AuthenticationSchemes.Negotiate;
options.Authentication.AllowAnonymous = false;
})
Until you realize that there's a whole other article about hosting in HTTP.sys, so you may find some other reasons it might break something else.
It might be easier to host it in IIS (instead of a Windows Service) and let IIS handle the Windows Authentication.
Is there a reason you decided to host in a Windows Service in the first place?
Upvotes: 3
Reputation: 271
There are different web servers that can be used with a .NET Core Web Application:
Windows authentication in IIS / IIS Express works without problems.
Kestrel can only use Negotiate (Kerberos). This means you need to setup a trusted connection with a service principle name (SPN). This can be done with the setspn command line tool. Unfortunally I have no experience in it because on a development machine you tend to skip that.
http.sys can use NTLM but is not compatible with IIS / IIS Express. This means you can't use Visual Studio debugging when using this. As a workarround you can add an environment variable that decides to use http.sys or not. For example add the following line to the "Project" profile in the launchSettings.json:
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"USE_HTTP_SYS": "true"
}
Now it's possible to conditional use http.sys or not:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args).ConfigureWebHostDefaults(webBuilder =>
{
if (bool.Parse(Environment.GetEnvironmentVariable("USE_HTTP_SYS") ?? "false"))
{
webBuilder.UseHttpSys(options =>
{
options.Authentication.Schemes = AuthenticationSchemes.NTLM;
options.Authentication.AllowAnonymous = false;
});
}
webBuilder.UseStartup<Startup>();
});
As a sidenote, since .NET Core 3.0 there is a new interface "IHostBuilder" instead of "IWebHostBuilder" (only exists for backward compatibility).
Sadly, when you use "dotnet run" and goto the website you might see an error message:
Kestrel brings it's own certificate management. It runs in user mode and looks for the certificates at "CurrentUser\My". In constrast http.sys is kernel mode, which means the current user is not known. http.sys looks for the certificate at "LocalMachine\My".
Because http.sys doesn't know which certificate is used on the port, you also need to assign the certificate to the https port of the .net application. This needs to be done via PowerShell as a local administrator:
$cert = Get-ChildItem -Path Cert:\LocalMachine\My | Where { $_.Subject -eq "CN=localhost" } | Select -First 1
netsh http add sslcert ipport=0.0.0.0:5001 appid='{12345678-1234-43f8-a778-f05f3c6b9709}' certhash=$($cert.Thumbprint)
Note that "CN=localhost" is the uri, "0.0.0.0:5001" is the port of the dotnet app and the appid is a random identifier (if your app has an guid you can use that too, but it's not required).
If you don't have a certificate (e.g. for development) you might create a self signed certificate for the machine (Win10 and admin right required):
$rootextension = [System.Security.Cryptography.X509Certificates.X509BasicConstraintsExtension]::new($true, $true, 0, $true)
$cert = New-SelfSignedCertificate -Subject "CN=localhost" -FriendlyName "Development localhost Certificate" -Extension $rootextension -NotAfter ([DateTime]::Now).AddYears(10) -KeyUsage DigitalSignature,KeyEncipherment,DataEncipherment -CertStoreLocation "Cert:\LocalMachine\My" -KeyExportPolicy Exportable
Upvotes: 26
Reputation: 1656
With .Net Core 3.0 you can use Windows Authentication with Kestrel. There is a Nuget Package for it: Microsoft.AspNetCore.Authentication.Negotiate
You then can add it in Startup.ConfigureServices:
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
For more Information also see:
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-3.0&tabs=visual-studio#kestrel
Upvotes: 19