diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/IISDefaults.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/IISDefaults.cs
index db7ea22732..957273c094 100644
--- a/src/Microsoft.AspNetCore.Server.IISIntegration/IISDefaults.cs
+++ b/src/Microsoft.AspNetCore.Server.IISIntegration/IISDefaults.cs
@@ -5,6 +5,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
{
public class IISDefaults
{
+ public static readonly string AuthenticationScheme = "Windows";
public const string Negotiate = "Negotiate";
public const string Ntlm = "NTLM";
}
diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/IISMiddleware.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/IISMiddleware.cs
index 5729c9b0cb..6d3e9ca79e 100644
--- a/src/Microsoft.AspNetCore.Server.IISIntegration/IISMiddleware.cs
+++ b/src/Microsoft.AspNetCore.Server.IISIntegration/IISMiddleware.cs
@@ -18,8 +18,6 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
{
public class IISMiddleware
{
- public static readonly string AuthenticationScheme = "Windows";
-
private const string MSAspNetCoreClientCert = "MS-ASPNETCORE-CLIENTCERT";
private const string MSAspNetCoreToken = "MS-ASPNETCORE-TOKEN";
@@ -50,10 +48,9 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
_next = next;
_options = options.Value;
-
if (_options.ForwardWindowsAuthentication)
{
- authentication.AddScheme(new AuthenticationScheme(AuthenticationScheme, displayName: null, handlerType: typeof(AuthenticationHandler)));
+ authentication.AddScheme(new AuthenticationScheme(IISDefaults.AuthenticationScheme, displayName: null, handlerType: typeof(AuthenticationHandler)));
}
_pairingToken = pairingToken;
@@ -94,7 +91,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
if (_options.ForwardWindowsAuthentication)
{
- var result = await httpContext.AuthenticateAsync(AuthenticationScheme);
+ var result = await httpContext.AuthenticateAsync(IISDefaults.AuthenticationScheme);
if (result.Succeeded)
{
httpContext.User = result.Principal;
diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/IISOptions.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/IISOptions.cs
index c37ad2aef4..dd012eef86 100644
--- a/src/Microsoft.AspNetCore.Server.IISIntegration/IISOptions.cs
+++ b/src/Microsoft.AspNetCore.Server.IISIntegration/IISOptions.cs
@@ -1,4 +1,4 @@
-// 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.
namespace Microsoft.AspNetCore.Builder
@@ -6,14 +6,14 @@ namespace Microsoft.AspNetCore.Builder
public class IISOptions
{
///
- /// If true authentication middleware will try to authenticate using platform handler windows authentication
- /// If false authentication middleware won't be added
+ /// If true authentication middleware will try to authenticate using AspNetCoreModule windows authentication
+ /// If false authentication components won't be added
///
- public bool ForwardWindowsAuthentication { get; set; } = true;
+ internal bool ForwardWindowsAuthentication { get; set; } = true;
///
/// Populates the ITLSConnectionFeature if the MS-ASPNETCORE-CLIENTCERT request header is present.
///
public bool ForwardClientCertificate { get; set; } = true;
}
-}
\ No newline at end of file
+}
diff --git a/src/Microsoft.AspNetCore.Server.IISIntegration/WebHostBuilderIISExtensions.cs b/src/Microsoft.AspNetCore.Server.IISIntegration/WebHostBuilderIISExtensions.cs
index 36718f8394..e4c5875bd6 100644
--- a/src/Microsoft.AspNetCore.Server.IISIntegration/WebHostBuilderIISExtensions.cs
+++ b/src/Microsoft.AspNetCore.Server.IISIntegration/WebHostBuilderIISExtensions.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
+using System.Linq;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
@@ -17,6 +18,7 @@ namespace Microsoft.AspNetCore.Hosting
private static readonly string ServerPort = "PORT";
private static readonly string ServerPath = "APPL_PATH";
private static readonly string PairingToken = "TOKEN";
+ private static readonly string IISAuth = "IIS_HTTPAUTH";
///
/// Configures the port and base path the server should listen on when running behind AspNetCoreModule.
@@ -40,12 +42,32 @@ namespace Microsoft.AspNetCore.Hosting
var port = hostBuilder.GetSetting(ServerPort) ?? Environment.GetEnvironmentVariable($"ASPNETCORE_{ServerPort}");
var path = hostBuilder.GetSetting(ServerPath) ?? Environment.GetEnvironmentVariable($"ASPNETCORE_{ServerPath}");
var pairingToken = hostBuilder.GetSetting(PairingToken) ?? Environment.GetEnvironmentVariable($"ASPNETCORE_{PairingToken}");
+ var iisAuth = hostBuilder.GetSetting(IISAuth) ?? Environment.GetEnvironmentVariable($"ASPNETCORE_{IISAuth}");
if (!string.IsNullOrEmpty(port) && !string.IsNullOrEmpty(path) && !string.IsNullOrEmpty(pairingToken))
{
// Set flag to prevent double service configuration
hostBuilder.UseSetting(nameof(UseIISIntegration), true.ToString());
+ var enableAuth = false;
+ if (string.IsNullOrEmpty(iisAuth))
+ {
+ // back compat with older ANCM versions
+ enableAuth = true;
+ }
+ else
+ {
+ // Lightup a new ANCM variable that tells us if auth is enabled.
+ foreach (var authType in iisAuth.Split(';'))
+ {
+ if (!string.Equals(authType, "anonymous", StringComparison.OrdinalIgnoreCase))
+ {
+ enableAuth = true;
+ break;
+ }
+ }
+ }
+
var address = "http://localhost:" + port;
hostBuilder.CaptureStartupErrors(true);
@@ -59,6 +81,10 @@ namespace Microsoft.AspNetCore.Hosting
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
+ services.Configure(options =>
+ {
+ options.ForwardWindowsAuthentication = enableAuth;
+ });
services.AddAuthenticationCore();
});
}
diff --git a/test/IISIntegration.FunctionalTests/HelloWorldTest.cs b/test/IISIntegration.FunctionalTests/HelloWorldTest.cs
index 011fa521b4..6007c1ff13 100644
--- a/test/IISIntegration.FunctionalTests/HelloWorldTest.cs
+++ b/test/IISIntegration.FunctionalTests/HelloWorldTest.cs
@@ -85,6 +85,10 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
response = await deploymentResult.HttpClient.GetAsync("/BodyLimit");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal("null", responseText);
+
+ response = await deploymentResult.HttpClient.GetAsync("/Auth");
+ responseText = await response.Content.ReadAsStringAsync();
+ Assert.True("backcompat;Windows".Equals(responseText) || "latest;null".Equals(responseText), "Auth");
}
catch (XunitException)
{
diff --git a/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/IISMiddlewareTests.cs b/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/IISMiddlewareTests.cs
index 5dbb652b14..b5136fd65e 100644
--- a/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/IISMiddlewareTests.cs
+++ b/test/Microsoft.AspNetCore.Server.IISIntegration.Tests/IISMiddlewareTests.cs
@@ -156,7 +156,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
app.Run(async context =>
{
var auth = context.RequestServices.GetRequiredService();
- var windows = await auth.GetSchemeAsync(IISMiddleware.AuthenticationScheme);
+ var windows = await auth.GetSchemeAsync(IISDefaults.AuthenticationScheme);
Assert.NotNull(windows);
Assert.Null(windows.DisplayName);
Assert.Equal("Microsoft.AspNetCore.Server.IISIntegration.AuthenticationHandler", windows.HandlerType.FullName);
@@ -197,7 +197,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
{
var auth = context.RequestServices.GetService();
Assert.NotNull(auth);
- var windowsAuth = await auth.GetSchemeAsync(IISMiddleware.AuthenticationScheme);
+ var windowsAuth = await auth.GetSchemeAsync(IISDefaults.AuthenticationScheme);
if (forward)
{
Assert.NotNull(windowsAuth);
diff --git a/test/TestSites/StartupHelloWorld.cs b/test/TestSites/StartupHelloWorld.cs
index 41696fb9fb..1fa394eba8 100644
--- a/test/TestSites/StartupHelloWorld.cs
+++ b/test/TestSites/StartupHelloWorld.cs
@@ -1,9 +1,13 @@
// 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.Linq;
+using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features;
+using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
namespace TestSites
@@ -12,23 +16,42 @@ namespace TestSites
{
public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
{
- app.Run(ctx =>
+ app.Run(async ctx =>
{
if (ctx.Request.Path.Value.StartsWith("/Path"))
{
- return ctx.Response.WriteAsync(ctx.Request.Path.Value);
+ await ctx.Response.WriteAsync(ctx.Request.Path.Value);
+ return;
}
if (ctx.Request.Path.Value.StartsWith("/Query"))
{
- return ctx.Response.WriteAsync(ctx.Request.QueryString.Value);
+ await ctx.Response.WriteAsync(ctx.Request.QueryString.Value);
+ return;
}
if (ctx.Request.Path.Value.StartsWith("/BodyLimit"))
{
- return ctx.Response.WriteAsync(
+ await ctx.Response.WriteAsync(
ctx.Features.Get()?.MaxRequestBodySize?.ToString() ?? "null");
+ return;
}
- return ctx.Response.WriteAsync("Hello World");
+ if (ctx.Request.Path.StartsWithSegments("/Auth"))
+ {
+ var iisAuth = Environment.GetEnvironmentVariable("ASPNETCORE_IIS_HTTPAUTH");
+ var authProvider = ctx.RequestServices.GetService();
+ var authScheme = (await authProvider.GetAllSchemesAsync()).SingleOrDefault();
+ if (string.IsNullOrEmpty(iisAuth))
+ {
+ await ctx.Response.WriteAsync("backcompat;" + authScheme?.Name ?? "null");
+ }
+ else
+ {
+ await ctx.Response.WriteAsync("latest;" + authScheme?.Name ?? "null");
+ }
+ return;
+ }
+
+ await ctx.Response.WriteAsync("Hello World");
});
}
}
diff --git a/test/TestSites/StartupNtlmAuthentication.cs b/test/TestSites/StartupNtlmAuthentication.cs
index 480563ecb5..167f627a1a 100644
--- a/test/TestSites/StartupNtlmAuthentication.cs
+++ b/test/TestSites/StartupNtlmAuthentication.cs
@@ -74,7 +74,7 @@ namespace TestSites
}
else
{
- return context.ChallengeAsync(IISMiddleware.AuthenticationScheme);
+ return context.ChallengeAsync(IISDefaults.AuthenticationScheme);
}
}