Consolidate Windows Auth config #10530 (#11421)

This commit is contained in:
Chris Ross 2019-06-22 10:39:10 -07:00 committed by GitHub
parent 6ecfdf2c49
commit 3ce6c1dc5b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 303 additions and 68 deletions

View File

@ -15,6 +15,17 @@ namespace Microsoft.AspNetCore.Hosting.Server
System.Threading.Tasks.Task StartAsync<TContext>(Microsoft.AspNetCore.Hosting.Server.IHttpApplication<TContext> application, System.Threading.CancellationToken cancellationToken);
System.Threading.Tasks.Task StopAsync(System.Threading.CancellationToken cancellationToken);
}
public partial interface IServerIntegratedAuth
{
string AuthenticationScheme { get; }
bool IsEnabled { get; }
}
public partial class ServerIntegratedAuth : Microsoft.AspNetCore.Hosting.Server.IServerIntegratedAuth
{
public ServerIntegratedAuth() { }
public string AuthenticationScheme { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public bool IsEnabled { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
}
namespace Microsoft.AspNetCore.Hosting.Server.Features
{

View File

@ -0,0 +1,21 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Hosting.Server
{
/// <summary>
/// Used by servers to advertise if they support integrated Windows authentication, if it's enabled, and it's scheme.
/// </summary>
public interface IServerIntegratedAuth
{
/// <summary>
/// Indicates if integrated Windows authentication is enabled for the current application instance.
/// </summary>
bool IsEnabled { get; }
/// <summary>
/// The name of the authentication scheme for the server authentication handler.
/// </summary>
string AuthenticationScheme { get; }
}
}

View File

@ -0,0 +1,21 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.AspNetCore.Hosting.Server
{
/// <summary>
/// Used by servers to advertise if they support integrated Windows authentication, if it's enabled, and it's scheme.
/// </summary>
public class ServerIntegratedAuth : IServerIntegratedAuth
{
/// <summary>
/// Indicates if integrated Windows authentication is enabled for the current application instance.
/// </summary>
public bool IsEnabled { get; set;}
/// <summary>
/// The name of the authentication scheme for the server authentication handler.
/// </summary>
public string AuthenticationScheme { get; set; }
}
}

View File

@ -7,5 +7,6 @@
<Compile Include="Microsoft.AspNetCore.Authentication.Negotiate.netcoreapp3.0.cs" />
<Reference Include="Microsoft.AspNetCore.Authentication" />
<Reference Include="Microsoft.AspNetCore.Connections.Abstractions" />
<Reference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" />
</ItemGroup>
</Project>

View File

@ -51,6 +51,11 @@ namespace Microsoft.AspNetCore.Authentication.Negotiate
public bool PersistKerberosCredentials { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
public bool PersistNtlmCredentials { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } }
}
public partial class PostConfigureNegotiateOptions : Microsoft.Extensions.Options.IPostConfigureOptions<Microsoft.AspNetCore.Authentication.Negotiate.NegotiateOptions>
{
public PostConfigureNegotiateOptions(System.Collections.Generic.IEnumerable<Microsoft.AspNetCore.Hosting.Server.IServerIntegratedAuth> serverAuthServices, Microsoft.Extensions.Logging.ILogger<Microsoft.AspNetCore.Authentication.Negotiate.NegotiateHandler> logger) { }
public void PostConfigure(string name, Microsoft.AspNetCore.Authentication.Negotiate.NegotiateOptions options) { }
}
}
namespace Microsoft.Extensions.DependencyInjection
{

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
@ -9,6 +9,7 @@
<Reference Include="Microsoft.AspNetCore" />
<Reference Include="Microsoft.AspNetCore.Authentication.Negotiate" />
<Reference Include="Microsoft.AspNetCore.Authorization.Policy" />
<Reference Include="Microsoft.AspNetCore.Server.HttpSys" />
<Reference Include="Microsoft.Extensions.Hosting" />
</ItemGroup>

View File

@ -1,7 +1,9 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.HttpSys;
using Microsoft.Extensions.Hosting;
namespace NegotiateAuthSample
@ -17,6 +19,14 @@ namespace NegotiateAuthSample
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
if (string.Equals("HttpSys", webBuilder.GetSetting("server"), StringComparison.OrdinalIgnoreCase))
{
webBuilder.UseHttpSys(options =>
{
options.Authentication.AllowAnonymous = true;
options.Authentication.Schemes = AuthenticationSchemes.Negotiate;
});
}
webBuilder.UseStartup<Startup>();
});
}

View File

@ -1,6 +1,6 @@
{
"iisSettings": {
"windowsAuthentication": false,
"windowsAuthentication": true,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:6449",
@ -12,16 +12,27 @@
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_SERVER": "IISOutOfProc",
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"HttpSys": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_SERVER": "HttpSys",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:5000"
},
"NegotiateAuthSample": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_SERVER": "Kestrel",
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:5001;http://localhost:5000"
}
}
}
}

View File

@ -14,6 +14,7 @@ namespace Microsoft.Extensions.Logging
private static Action<ILogger, Exception> _exceptionProcessingAuth;
private static Action<ILogger, Exception> _challengeNegotiate;
private static Action<ILogger, Exception> _reauthenticating;
private static Action<ILogger, Exception> _deferring;
static NegotiateLoggingExtensions()
{
@ -45,6 +46,10 @@ namespace Microsoft.Extensions.Logging
eventId: new EventId(7, "Reauthenticating"),
logLevel: LogLevel.Debug,
formatString: "Negotiate data received for an already authenticated connection, Re-authenticating.");
_deferring = LoggerMessage.Define(
eventId: new EventId(8, "Deferring"),
logLevel: LogLevel.Information,
formatString: "Deferring to the server's implementation of Windows Authentication.");
}
public static void IncompleteNegotiateChallenge(this ILogger logger)
@ -67,5 +72,8 @@ namespace Microsoft.Extensions.Logging
public static void Reauthenticating(this ILogger logger)
=> _reauthenticating(logger, null);
public static void Deferring(this ILogger logger)
=> _deferring(logger, null);
}
}

View File

@ -11,6 +11,7 @@
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Authentication" />
<Reference Include="Microsoft.AspNetCore.Connections.Abstractions" />
<Reference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" />
</ItemGroup>
</Project>

View File

@ -4,6 +4,8 @@
using System;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.DependencyInjection
{
@ -49,13 +51,7 @@ namespace Microsoft.Extensions.DependencyInjection
/// <returns>The original builder.</returns>
public static AuthenticationBuilder AddNegotiate(this AuthenticationBuilder builder, string authenticationScheme, string displayName, Action<NegotiateOptions> configureOptions)
{
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable($"ASPNETCORE_TOKEN")))
{
throw new NotSupportedException(
"The Negotiate authentication handler must not be used with IIS out-of-process mode or similar reverse proxies that share connections between users."
+ " Use the Windows Authentication features available within IIS or IIS Express.");
}
builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<NegotiateOptions>, PostConfigureNegotiateOptions>());
return builder.AddScheme<NegotiateOptions, NegotiateHandler>(authenticationScheme, displayName, configureOptions);
}
}

View File

@ -67,11 +67,12 @@ namespace Microsoft.AspNetCore.Authentication.Negotiate
{
try
{
if (_requestProcessed)
if (_requestProcessed || Options.DeferToServer)
{
// This request was already processed but something is re-executing it like an exception handler.
// Don't re-run because we could corrupt the connection state, e.g. if this was a stage2 NTLM request
// that we've already completed the handshake for.
// Or we're in deferral mode where we let the server handle the authentication.
return false;
}

View File

@ -33,6 +33,12 @@ namespace Microsoft.AspNetCore.Authentication.Negotiate
/// </summary>
public bool PersistNtlmCredentials { get; set; } = true;
/// <summary>
/// Indicates if integrated server Windows Auth is being used instead of this handler.
/// See <see cref="PostConfigureNegotiateOptions"/>.
/// </summary>
internal bool DeferToServer { get; set; }
// For testing
internal INegotiateStateFactory StateFactory { get; set; } = new ReflectedNegotiateStateFactory();
}

View File

@ -0,0 +1,64 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Authentication.Negotiate
{
/// <summary>
/// Reconfigures the NegotiateOptions to defer to the integrated server authentication if present.
/// </summary>
public class PostConfigureNegotiateOptions : IPostConfigureOptions<NegotiateOptions>
{
private readonly IServerIntegratedAuth _serverAuth;
private readonly ILogger<NegotiateHandler> _logger;
/// <summary>
/// Creates a new <see cref="PostConfigureNegotiateOptions"/>
/// </summary>
/// <param name="serverAuthServices"></param>
/// <param name="logger"></param>
public PostConfigureNegotiateOptions(IEnumerable<IServerIntegratedAuth> serverAuthServices, ILogger<NegotiateHandler> logger)
{
_serverAuth = serverAuthServices.LastOrDefault();
_logger = logger;
}
/// <summary>
/// Invoked to post configure a TOptions instance.
/// </summary>
/// <param name="name">The name of the options instance being configured.</param>
/// <param name="options">The options instance to configure.</param>
public void PostConfigure(string name, NegotiateOptions options)
{
// If the server supports integrated authentication...
if (_serverAuth != null)
{
// And it's on...
if (_serverAuth.IsEnabled)
{
// Forward to the server if something else wasn't already configured.
if (options.ForwardDefault == null)
{
Debug.Assert(_serverAuth.AuthenticationScheme != null);
options.ForwardDefault = _serverAuth.AuthenticationScheme;
options.DeferToServer = true;
_logger.Deferring();
}
}
// Otherwise fail, you shouldn't be using this auth handler on a server that supports integrated auth.
else
{
throw new InvalidOperationException("The Negotiate Authentication handler cannot be used on a server that directly supports Windows Authentication."
+ " Enable Windows Authentication for the server and the Negotiate Authentication handler will defer to it.");
}
}
}
}
}

View File

@ -0,0 +1,75 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Xunit;
namespace Microsoft.AspNetCore.Authentication.Negotiate
{
public class ServerDeferralTests
{
[Fact]
public async Task ServerDoesNotSupportAuth_NoError()
{
using var host = await CreateHostAsync(supportsAuth: false);
var options = host.Services.GetRequiredService<IOptions<NegotiateOptions>>().Value;
Assert.False(options.DeferToServer);
Assert.Null(options.ForwardDefault);
}
[Fact]
public async Task ServerSupportsAuthButDisabled_Error()
{
using var host = await CreateHostAsync(supportsAuth: true, isEnabled: false);
var ex = Assert.Throws<InvalidOperationException>(() => host.Services.GetRequiredService<IOptions<NegotiateOptions>>().Value);
Assert.Equal("The Negotiate Authentication handler cannot be used on a server that directly supports Windows Authentication."
+ " Enable Windows Authentication for the server and the Negotiate Authentication handler will defer to it.", ex.Message);
}
[Fact]
public async Task ServerSupportsAuthAndEnabled_Deferred()
{
using var host = await CreateHostAsync(supportsAuth: true, isEnabled: true, authScheme: "DeferralScheme");
var options = host.Services.GetRequiredService<IOptions<NegotiateOptions>>().Value;
Assert.True(options.DeferToServer);
Assert.Equal("DeferralScheme", options.ForwardDefault);
}
private static async Task<IHost> CreateHostAsync(bool supportsAuth = false, bool isEnabled = false, string authScheme = null)
{
var builder = new HostBuilder()
.ConfigureServices(services =>
{
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
if (supportsAuth)
{
services.AddSingleton<IServerIntegratedAuth>(new ServerIntegratedAuth()
{
IsEnabled = isEnabled,
AuthenticationScheme = authScheme,
});
}
})
.ConfigureWebHost(webHostBuilder =>
{
webHostBuilder.UseTestServer();
webHostBuilder.Configure(app =>
{
app.UseAuthentication();
});
});
return await builder.StartAsync();
}
}
}

View File

@ -162,6 +162,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.HostFi
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.IIS", "..\Servers\IIS\IIS\src\Microsoft.AspNetCore.Server.IIS.csproj", "{666AFB4D-68A5-4621-BB55-2CD82F0FB1F8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.AspNetCore.Server.HttpSys", "..\Servers\HttpSys\src\Microsoft.AspNetCore.Server.HttpSys.csproj", "{D6C3C4A9-197B-47B5-8B72-35047CBC4F22}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -420,6 +422,10 @@ Global
{666AFB4D-68A5-4621-BB55-2CD82F0FB1F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{666AFB4D-68A5-4621-BB55-2CD82F0FB1F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{666AFB4D-68A5-4621-BB55-2CD82F0FB1F8}.Release|Any CPU.Build.0 = Release|Any CPU
{D6C3C4A9-197B-47B5-8B72-35047CBC4F22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D6C3C4A9-197B-47B5-8B72-35047CBC4F22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D6C3C4A9-197B-47B5-8B72-35047CBC4F22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D6C3C4A9-197B-47B5-8B72-35047CBC4F22}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -500,6 +506,7 @@ Global
{16C26D50-6849-4BA4-AEB6-E5C9AA2369A2} = {A3766414-EB5C-40F7-B031-121804ED5D0A}
{A665A1F8-D1A4-42AC-B8E9-71B6F57481D8} = {A3766414-EB5C-40F7-B031-121804ED5D0A}
{666AFB4D-68A5-4621-BB55-2CD82F0FB1F8} = {A3766414-EB5C-40F7-B031-121804ED5D0A}
{D6C3C4A9-197B-47B5-8B72-35047CBC4F22} = {A3766414-EB5C-40F7-B031-121804ED5D0A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {ABF8089E-43D0-4010-84A7-7A9DCFE49357}

View File

@ -1,10 +1,11 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Server.HttpSys;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Microsoft.AspNetCore.Hosting
{
@ -23,6 +24,15 @@ namespace Microsoft.AspNetCore.Hosting
{
return hostBuilder.ConfigureServices(services => {
services.AddSingleton<IServer, MessagePump>();
services.AddSingleton<IServerIntegratedAuth>(services =>
{
var options = services.GetRequiredService<IOptions<HttpSysOptions>>().Value;
return new ServerIntegratedAuth()
{
IsEnabled = options.Authentication.Schemes != AuthenticationSchemes.None,
AuthenticationScheme = HttpSysDefaults.AuthenticationScheme,
};
});
services.AddAuthenticationCore();
});
}

View File

@ -40,6 +40,11 @@ namespace Microsoft.AspNetCore.Hosting
services.AddSingleton<IServer, IISHttpServer>();
services.AddSingleton<IStartupFilter>(new IISServerSetupFilter(iisConfigData.pwzVirtualApplicationPath));
services.AddAuthenticationCore();
services.AddSingleton<IServerIntegratedAuth>(_ => new ServerIntegratedAuth()
{
IsEnabled = iisConfigData.fWindowsAuthEnabled || iisConfigData.fBasicAuthEnabled,
AuthenticationScheme = IISServerDefaults.AuthenticationScheme
});
services.Configure<IISServerOptions>(
options => {
options.ServerAddresses = iisConfigData.pwzBindings.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

View File

@ -7,6 +7,7 @@
<Compile Include="Microsoft.AspNetCore.Server.IISIntegration.netcoreapp3.0.cs" />
<Reference Include="Microsoft.AspNetCore.Authentication.Core" />
<Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
<Reference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" />
<Reference Include="Microsoft.AspNetCore.Http.Extensions" />
<Reference Include="Microsoft.AspNetCore.Http" />
<Reference Include="Microsoft.AspNetCore.HttpOverrides" />

View File

@ -13,6 +13,7 @@
<ItemGroup>
<Reference Include="Microsoft.AspNetCore.Authentication.Core" />
<Reference Include="Microsoft.AspNetCore.Hosting.Abstractions" />
<Reference Include="Microsoft.AspNetCore.Hosting.Server.Abstractions" />
<Reference Include="Microsoft.AspNetCore.Http.Extensions" />
<Reference Include="Microsoft.AspNetCore.Http" />
<Reference Include="Microsoft.AspNetCore.HttpOverrides" />

View File

@ -2,13 +2,12 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Runtime.InteropServices;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting.Server;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.AspNetCore.Server.IISIntegration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Hosting.Server;
namespace Microsoft.AspNetCore.Hosting
{
@ -82,9 +81,14 @@ namespace Microsoft.AspNetCore.Hosting
hostBuilder.ConfigureServices(services =>
{
// Delay register the url so users don't accidently overwrite it.
// Delay register the url so users don't accidentally overwrite it.
hostBuilder.UseSetting(WebHostDefaults.ServerUrlsKey, address);
hostBuilder.PreferHostingUrls(true);
services.AddSingleton<IServerIntegratedAuth>(_ => new ServerIntegratedAuth()
{
IsEnabled = enableAuth,
AuthenticationScheme = IISDefaults.AuthenticationScheme
});
services.AddSingleton<IStartupFilter>(new IISSetupFilter(pairingToken, new PathString(path), isWebSocketsSupported));
services.Configure<ForwardedHeadersOptions>(options =>
{

View File

@ -13,12 +13,10 @@ namespace ServerComparison.TestSites
{
public static void Main(string[] args)
{
var config = new ConfigurationBuilder()
.AddCommandLine(args)
.Build();
var builder = new WebHostBuilder()
.UseConfiguration(config)
.UseConfiguration(new ConfigurationBuilder()
.AddCommandLine(args)
.Build())
.ConfigureLogging((_, factory) =>
{
factory.AddConsole();
@ -26,37 +24,28 @@ namespace ServerComparison.TestSites
})
.UseStartup("ServerComparison.TestSites");
// Switch between Kestrel, IIS, and HttpSys for different tests. Default to Kestrel for normal app execution.
if (string.Equals(builder.GetSetting("server"), "Microsoft.AspNetCore.Server.HttpSys", StringComparison.Ordinal))
{
if (string.Equals(builder.GetSetting("environment") ??
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"),
"NtlmAuthentication", System.StringComparison.Ordinal))
{
// Set up NTLM authentication for HttpSys as follows.
// For IIS and IISExpress use inetmgr to setup NTLM authentication on the application or
// modify the applicationHost.config to enable NTLM.
builder.UseHttpSys(options =>
{
options.Authentication.AllowAnonymous = true;
options.Authentication.Schemes =
AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM;
});
}
else
{
builder.UseHttpSys();
}
}
else
{
// Check that we are not using IIS inproc before we add Kestrel.
builder.UseKestrel();
}
builder.UseKestrel();
builder.UseIISIntegration();
builder.UseIIS();
// Switch between Kestrel, IIS, and HttpSys for different tests. Default to Kestrel for normal app execution.
if (string.Equals(builder.GetSetting("server"), "Microsoft.AspNetCore.Server.HttpSys", StringComparison.OrdinalIgnoreCase))
{
builder.UseHttpSys(options =>
{
if (string.Equals(builder.GetSetting("environment") ??
Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"),
"NtlmAuthentication", StringComparison.OrdinalIgnoreCase))
{
// Set up NTLM authentication for HttpSys as follows.
// For IIS and IISExpress use inetmgr to setup NTLM authentication on the application or
// modify the applicationHost.config to enable NTLM.
options.Authentication.AllowAnonymous = true;
options.Authentication.Schemes = AuthenticationSchemes.Negotiate | AuthenticationSchemes.NTLM;
}
});
}
var host = builder.Build();
host.Run();

View File

@ -6,8 +6,6 @@ using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Server.IISIntegration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
@ -15,27 +13,15 @@ namespace ServerComparison.TestSites
{
public class StartupNtlmAuthentication
{
public IConfiguration Configuration { get; }
public bool IsKestrel => string.Equals(Configuration["server"], "Microsoft.AspNetCore.Server.Kestrel");
public StartupNtlmAuthentication(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
services.AddSingleton<IClaimsTransformation, OneTransformPerRequest>();
if (IsKestrel)
{
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
}
else
{
services.AddAuthentication(IISDefaults.AuthenticationScheme);
}
// https://github.com/aspnet/AspNetCore/issues/11462
// services.AddSingleton<IClaimsTransformation, OneTransformPerRequest>();
// This will deffer to the server implementations when available.
services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
.AddNegotiate();
}
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)