#371 Conditionally register auth scheme base on ANCM variable

This commit is contained in:
Chris R 2017-06-05 14:30:07 -07:00
parent 16c70d6dda
commit c261b37fda
8 changed files with 69 additions and 18 deletions

View File

@ -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";
}

View File

@ -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;

View File

@ -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
{
/// <summary>
/// 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
/// </summary>
public bool ForwardWindowsAuthentication { get; set; } = true;
internal bool ForwardWindowsAuthentication { get; set; } = true;
/// <summary>
/// Populates the ITLSConnectionFeature if the MS-ASPNETCORE-CLIENTCERT request header is present.
/// </summary>
public bool ForwardClientCertificate { get; set; } = true;
}
}
}

View File

@ -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";
/// <summary>
/// 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<IISOptions>(options =>
{
options.ForwardWindowsAuthentication = enableAuth;
});
services.AddAuthenticationCore();
});
}

View File

@ -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)
{

View File

@ -156,7 +156,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
app.Run(async context =>
{
var auth = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>();
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<IAuthenticationSchemeProvider>();
Assert.NotNull(auth);
var windowsAuth = await auth.GetSchemeAsync(IISMiddleware.AuthenticationScheme);
var windowsAuth = await auth.GetSchemeAsync(IISDefaults.AuthenticationScheme);
if (forward)
{
Assert.NotNull(windowsAuth);

View File

@ -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<IHttpMaxRequestBodySizeFeature>()?.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<IAuthenticationSchemeProvider>();
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");
});
}
}

View File

@ -74,7 +74,7 @@ namespace TestSites
}
else
{
return context.ChallengeAsync(IISMiddleware.AuthenticationScheme);
return context.ChallengeAsync(IISDefaults.AuthenticationScheme);
}
}