Windows Authentication in ASP.NET Core Last Modified: 2017-03-28
Using Windows Authentication in ASP.NET Core Web Applications
ASP.NET Core Windows Authentication

Note that some of the content does not apply to RC1 or earlier versions and may not apply to later versions either.

General

Enable Windows Authentication

The server running the application must be configured to enable windows authentication and disable anonymous authentication. If anonymous authentication is enabled, then it will be used by default and no user information is collected or required.

Hosting Options

  • IIS + Kestrel: Windows authentication is configured in IIS (or Properties\launchSettings.json when debugging with Visual Studio and IIS Express).
  • WebListener: Windows authentication is configured in web host builder programmatically.

At the time of writing, windows authentication only works when the server is hosted on the Windows platform (IIS and WebListener are Windows-only).

Take a look at ASP.NET Core Hosting for setting up either hosting option.

Sources:

WebListener

When using WebListener, you need to set up the authentication scheme in WebListener options in Program.cs:

using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Net.Http.Server;

public static void Main(string[] args)
{
	var host = new WebHostBuilder()
		.UseWebListener(options =>
		{
			options.ListenerSettings.Authentication.Schemes = AuthenticationSchemes.NTLM; // <--
			options.ListenerSettings.Authentication.AllowAnonymous = false; // <--
		})
		.UseStartup<Startup>()
		.Build();

	host.Run();
}

Note: installing package Microsoft.Net.Http.Server from NuGet is required for accessing the AuthenticationSchemes class.

Sources:

IIS Integration

When using IIS Integration (Express or not), there are some configuration options that you can tweak. Add configuration in Startup.cs in the ConfigureServices method:

services.Configure<IISOptions>(options => {
	//options.AuthenticationDescriptions holds a list of allowed authentication schemes
	options.AutomaticAuthentication = true;
	options.ForwardClientCertificate = true;
	options.ForwardWindowsAuthentication = true;
});

All three options default to true at least when running on IIS Express through Visual Studio.

Source: https://docs.asp.net/en/latest/fundamentals/servers.html

IIS Express (when Debugging from Visual Studio)

In visual studio, right-click into the project properties and select the Debug tab. Check “Enable Windows Authentication” and uncheck “Enable Anonymous Authentication”

The values are stored in Properties\launchSettings.json:

{
  "iisSettings": {
    "windowsAuthentication": true,
    "anonymousAuthentication": false,
    ...
  },
  ...
}

Making this change also forces forwardWindowsAuthToken to true in web.config (aspNetCore-element under system.webServer) each time you start the app in debug mode.

IIS

Enable windows authentication in IIS application host configuration file which can be found in the system32\inetsrv directory.

NOTE: IIS Express application configuration file lives in $(solutionDir)\.vs\config\applicationhost.configsource when using Visual Studio 2015 (or %userprofile%\documents\iisexpress\config\applicationhost.config or somewhere else when using an earlier version). TODO not verified using IIS Express directly. The configuration does not affect the behaviour of IIS Express when debugging through Visual Studio.

The correct section can be found in configuration -> system.webServer -> security -> authentication -> windowsAuthentication.

The configuration should look as follows.

<windowsAuthentication enabled="true">
    <providers>
        <add value="Negotiate" />
        <add value="NTLM" />
    </providers>
</windowsAuthentication>

TODO May have to remove the Negotiate provider as per http://stackoverflow.com/questions/36946304/using-windows-authentication-in-asp-net?

Windows authentication can also be enabled using the Internet Information Services Manager: Go to the site’s Authentication settings, enable Windows Authentication and disable Anonymous Authentication.

Make sure that the forwardWindowsAuthToken is set to true in web.config (aspNetCore-element under system.webServer).

Sources:

Identity Impersonation

TODO For accessing further resources such as an SQL DB or other APIs with windows authentication.

Sources:

Accessing User Information

CSHtml

You can access user identity in .cshtml files by using, for example:

<pre>@Html.Raw(Json.Serialize(User, new Newtonsoft.Json.JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore }))</pre>
<p>Name: @User.Identity.Name</p>
<p>Authenticated: @User.Identity.IsAuthenticated</p>

If you need to access the HttpContext, you need to add the HttpContextAccessor service in Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
  ...
  services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
  ...
}

And in cshtml:

@inject IHttpContextAccessor httpContextaccessor

<pre>@Html.Raw(Json.Serialize(HttpContextAccessor.HttpContext.User.Identity, new Newtonsoft.Json.JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore }))</pre>

Source: http://stackoverflow.com/questions/38945678/access-cookie-in-layout-cshtml-in-asp-net-core

In MCV or WebAPI Controllers

var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
var userName = User.FindFirstValue(ClaimTypes.Name);
var userName2 = User.Identity.Name;

Requires package Microsoft.AspNetCore.Identity

Sources:

JavaScript

There is no way that I came across to get at the windows user information directly in JavaScript, except by injecting through script tags and cshtml.

Source: http://stackoverflow.com/questions/3013692/getting-windows-username-with-javascript

Calling API Methods from JavaScript

Make sure you include credentials in calls, e.g. with fetch:

fetch("/api/SampleData/WeatherForecasts", { credentials: 'include' })
  .then(response => { ... });

Authorization By Group Membership

Local groups:

  • Local groups are written without the domain part or prefixed with the host name: <group> or <hostname>\<group>.
  • Built-in local groups (e.g. BUILTIN\Administrators) are not recognized by name. You have to write the corresponding SID instead.
  • You can find out the SIDs by using the PsGetSid tool: https://technet.microsoft.com/en-us/sysinternals/bb897417.
  • The BUILTIN\Administrators group is not recognized even when using the correct SID.

Group membership shows as role membership in ASP.NET Core. You can enforce group membership directly with the Authorize attribute, with an authorization policy, or programmatically in the controller methods.

Authorize Attribute

Add [Authorize(Roles = @"<domain>\<group>")] attribute (or [Authorize(Roles = @"<domain>\<group1>,<domain>\<group2>")] for multiple allowed roles) to the controller or method.

Sources:

Authorization Policy

Add a new policy to service configuration in ConfigureServices method in Startup.cs:

services.AddAuthorization(options =>
{
  options.AddPolicy("RequireWindowsGroupMembership", policy => policy.RequireRole(@"<domain>\<group>"));  
});

To get the required group name from settings, add the group name into appsettings.json (note the double backslashes):

{
  "Logging": {
    ...
  },
  "WindowsGroup": "<domain>\\<group>"
}

Then read it in when configuring authorization:

services.AddAuthorization(options =>
{
  var windowsGroup = Configuration.GetValue<string>("WindowsGroup");
  options.AddPolicy("RequireWindowsGroupMembership", policy =>
  {
    policy.RequireAuthenticatedUser(); // Policy must have at least one requirement
    if (windowsGroup != null)
      policy.RequireRole(windowsGroup);
  });
});

Use a comma-separated string for multiple allowed roles: <domain>\<group1>,<domain>\<group2>.

Finally, add the authorize-attribute on the controller or method: [Authorize(Policy = "RequireWindowsGroupMembership")]

Sources:

The policy syntax allows for more elaborate authorization scenarios with custom requirements, such as activity/permission-based authentication

Programmatically

Check for role membership in controller method and return 403 Forbidden status code if not authorized.

[HttpGet("[action]")]
public IActionResult SomeValue()
{
  if (!User.IsInRole(@"Domain\Group")) return StatusCode(403);
  return Ok("Some Value");
}

Note that the return type of the method must be IActionResult.

Browser Settings

If you need automatic windows authentication, then you may have to enable it specifically in the client browser

  • IE (TODO verify same works in EDGE)
    • Advanced -> Enable Integrated Windows Authentication in Internet Options
    • Security -> Local intranet -> Custom level -> User Authentication -> Automatic logon / Prompt for user name and password
  • Chrome
    • Chrome uses settings in Windows’ internet options so the IE options should sufficesource
  • Firefox
    • about:config -> network.automatic-ntlm-auth.trusted-uris -> add url of application

Sources:

Different Domain or No Domain Binding

TODO I did not get this to work from a remote site, with or without VPN connection (flashes a new console window and dies instantly, unable to capture error message)

If you are developing on a computer that is not bound to a domain, or is bound to a different domain that the app should authenticate against, you can run the server like so:

runas /netonly /user:<user> "<command> <args...>"

where <user> is domain\username or username@domain.

IIS: you must establish trust between the two domains to be able to run app pools under a user in different domain than the server.

IIS: does this work at all when running as network service??

Sources: