Windows Authentication ====================== There are several ways how you can enable Windows authentication in ASP.NET Core (and thus in 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) .. Note:: We only have documentation for IIS hosting. If you want to contribute to the docs, please open a PR. thanks! On Windows using IIS hosting ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The typical ``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 DI that can be invoked via the authentication service. Typically in 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):: // configures IIS out-of-proc settings (see https://github.com/aspnet/AspNetCore/issues/14882) services.Configure(iis => { iis.AuthenticationDisplayName = "Windows"; iis.AutomaticAuthentication = false; }); // ..or configures IIS in-proc settings services.Configure(iis => { iis.AuthenticationDisplayName = "Windows"; iis.AutomaticAuthentication = false; }); You trigger Windows authentication by calling ``ChallengeAsync`` on 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:: private async Task 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"); } }