# Windows Authentication

> Guide to implementing Windows authentication in IdentityServer using various approaches including IIS hosting, HTTP.SYS hosting, and the Negotiate authentication handler, with detailed configuration instructions and code examples.

There are several ways how you can enable Windows authentication in ASP.NET Core (and thus in your IdentityServer).

* On Windows using IIS hosting (both in- and out-of process)
* On Windows using HTTP.SYS hosting
* On any platform using the Negotiate authentication handler (added in ASP.NET Core 3.0)

See the [Microsoft documentation](https://docs.microsoft.com/en-us/aspnet/core/security/authentication/windowsauth?view=aspnetcore-5.0\&tabs=visual-studio) for additional information.

## On Windows Using IIS hosting

[Section titled âOn Windows Using IIS hostingâ](#on-windows-using-iis-hosting)

The typical ASP.NET Core `CreateDefaultBuilder` host setup enables support for IIS-based Windows authentication when hosting in IIS. Make sure that Windows authentication is enabled in `launchSettings.json` or your IIS configuration.

The IIS integration layer will configure a Windows authentication handler into the ASP.NET Core service provider that can be invoked via the authentication service. Typically, in your IdentityServer it is advisable to disable the automatic behavior.

This is done in `ConfigureServices` (details vary depending on in-proc vs out-of-proc hosting)::

```cs
// configures IIS out-of-proc settings (see https://github.com/aspnet/AspNetCore/issues/14882)
builder.Services.Configure<IISOptions>(iis =>
{
    iis.AuthenticationDisplayName = "Windows";
    iis.AutomaticAuthentication = false;
});


// ...or configures IIS in-proc settings
builder.Services.Configure<IISServerOptions>(iis =>
{
    iis.AuthenticationDisplayName = "Windows";
    iis.AutomaticAuthentication = false;
});
```

You trigger Windows authentication by calling `ChallengeAsync` using the `Windows` scheme (or if you want to use a constant: `Microsoft.AspNetCore.Server.IISIntegration.IISDefaults.AuthenticationScheme`).

This will send the `Www-Authenticate` header back to the browser which will then re-load the current URL including the Windows identity. You can tell that Windows authentication was successful, when you call `AuthenticateAsync` on the `Windows` scheme and the principal returned is of type `WindowsPrincipal`.

The principal will have information like user and group SID and the Windows account name. The following snippet shows how to trigger authentication, and if successful convert the information into a standard `ClaimsPrincipal` for the temp-Cookie approach::

```cs
private async Task<IActionResult> ChallengeWindowsAsync(string returnUrl)
{
    // see if windows auth has already been requested and succeeded
    var result = await HttpContext.AuthenticateAsync("Windows");
    if (result?.Principal is WindowsPrincipal wp)
    {
        // we will issue the external cookie and then redirect the
        // user back to the external callback, in essence, treating windows
        // auth the same as any other external authentication mechanism
        var props = new AuthenticationProperties()
        {
            RedirectUri = Url.Action("Callback"),
            Items =
            {
                { "returnUrl", returnUrl },
                { "scheme", "Windows" },
            }
        };


        var id = new ClaimsIdentity("Windows");


        // the sid is a good sub value
        id.AddClaim(new Claim(JwtClaimTypes.Subject, wp.FindFirst(ClaimTypes.PrimarySid).Value));


        // the account name is the closest we have to a display name
        id.AddClaim(new Claim(JwtClaimTypes.Name, wp.Identity.Name));


        // add the groups as claims -- be careful if the number of groups is too large
        var wi = wp.Identity as WindowsIdentity;


        // translate group SIDs to display names
        var groups = wi.Groups.Translate(typeof(NTAccount));
        var roles = groups.Select(x => new Claim(JwtClaimTypes.Role, x.Value));
        id.AddClaims(roles);


        await HttpContext.SignInAsync(
            IdentityServerConstants.ExternalCookieAuthenticationScheme,
            new ClaimsPrincipal(id),
            props);
        return Redirect(props.RedirectUri);
    }
    else
    {
        // trigger windows auth
        // since windows auth don't support the redirect uri,
        // this URL is re-triggered when we call challenge
        return Challenge("Windows");
    }
}
```

A sample is provided [here](/identityserver/samples/ui/#windows-authentication-with-iis-hosting).
-----