IIS => Auth 2.0

This commit is contained in:
Hao Kung 2017-05-17 13:37:01 -07:00
parent 5761ddd284
commit 8ed21d56c8
10 changed files with 163 additions and 232 deletions

View File

@ -1,4 +1,4 @@
using System; using System;
using System.Linq; using System.Linq;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;

View File

@ -1,69 +1,71 @@
// 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Linq; using System.Globalization;
using System.Security.Claims; using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.AspNetCore.Http.Features.Authentication;
using Microsoft.Extensions.Internal; using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Server.IISIntegration namespace Microsoft.AspNetCore.Server.IISIntegration
{ {
internal class AuthenticationHandler : IAuthenticationHandler internal class AuthenticationHandler : IAuthenticationHandler
{ {
internal AuthenticationHandler(HttpContext httpContext, IISOptions options, ClaimsPrincipal user) private const string MSAspNetCoreWinAuthToken = "MS-ASPNETCORE-WINAUTHTOKEN";
private WindowsPrincipal _user;
private HttpContext _context;
internal AuthenticationScheme Scheme { get; private set; }
public Task<AuthenticateResult> AuthenticateAsync()
{ {
HttpContext = httpContext; var user = GetUser();
User = user; if (user != null)
Options = options;
}
internal HttpContext HttpContext { get; }
internal IISOptions Options { get; }
internal ClaimsPrincipal User { get; }
internal IAuthenticationHandler PriorHandler { get; set; }
public Task AuthenticateAsync(AuthenticateContext context)
{ {
if (ShouldHandleScheme(context.AuthenticationScheme)) return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(user, Scheme.Name)));
{
if (User != null)
{
context.Authenticated(User, properties: null, description: null);
} }
else else
{ {
context.NotAuthenticated(); return Task.FromResult(AuthenticateResult.None());
} }
} }
if (PriorHandler != null) private WindowsPrincipal GetUser()
{ {
return PriorHandler.AuthenticateAsync(context); if (_user == null)
{
var tokenHeader = _context.Request.Headers[MSAspNetCoreWinAuthToken];
int hexHandle;
if (!StringValues.IsNullOrEmpty(tokenHeader)
&& int.TryParse(tokenHeader, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hexHandle))
{
// Always create the identity if the handle exists, we need to dispose it so it does not leak.
var handle = new IntPtr(hexHandle);
var winIdentity = new WindowsIdentity(handle);
// WindowsIdentity just duplicated the handle so we need to close the original.
NativeMethods.CloseHandle(handle);
_context.Response.RegisterForDispose(winIdentity);
_user = new WindowsPrincipal(winIdentity);
}
} }
return TaskCache.CompletedTask; return _user;
} }
public Task ChallengeAsync(ChallengeContext context) public Task ChallengeAsync(ChallengeContext context)
{
// Some other provider may have already accepted this challenge. Having multiple providers with
// AutomaticChallenge = true is considered invalid, but changing the default would breaking
// normal Windows auth users.
if (!context.Accepted && ShouldHandleScheme(context.AuthenticationScheme))
{ {
switch (context.Behavior) switch (context.Behavior)
{ {
case ChallengeBehavior.Automatic: case ChallengeBehavior.Automatic:
// If there is a principal already, invoke the forbidden code path // If there is a principal already, invoke the forbidden code path
if (User == null) if (GetUser() == null)
{ {
goto case ChallengeBehavior.Unauthorized; goto case ChallengeBehavior.Unauthorized;
} }
@ -72,67 +74,31 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
goto case ChallengeBehavior.Forbidden; goto case ChallengeBehavior.Forbidden;
} }
case ChallengeBehavior.Unauthorized: case ChallengeBehavior.Unauthorized:
HttpContext.Response.StatusCode = 401; context.HttpContext.Response.StatusCode = 401;
// We would normally set the www-authenticate header here, but IIS does that for us. // We would normally set the www-authenticate header here, but IIS does that for us.
break; break;
case ChallengeBehavior.Forbidden: case ChallengeBehavior.Forbidden:
HttpContext.Response.StatusCode = 403; context.HttpContext.Response.StatusCode = 403;
break; break;
} }
context.Accept();
}
if (PriorHandler != null)
{
return PriorHandler.ChallengeAsync(context);
}
return TaskCache.CompletedTask; return TaskCache.CompletedTask;
} }
public void GetDescriptions(DescribeSchemesContext context) public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
{ {
foreach (var description in Options.AuthenticationDescriptions) Scheme = scheme;
{ _context = context;
context.Accept(description.Items); return TaskCache.CompletedTask;
}
if (PriorHandler != null)
{
PriorHandler.GetDescriptions(context);
}
} }
public Task SignInAsync(SignInContext context) public Task SignInAsync(SignInContext context)
{ {
// Not supported, fall through throw new NotSupportedException();
if (PriorHandler != null)
{
return PriorHandler.SignInAsync(context);
}
return TaskCache.CompletedTask;
} }
public Task SignOutAsync(SignOutContext context) public Task SignOutAsync(SignOutContext context)
{ {
// Not supported, fall through
if (PriorHandler != null)
{
return PriorHandler.SignOutAsync(context);
}
return TaskCache.CompletedTask; return TaskCache.CompletedTask;
} }
private bool ShouldHandleScheme(string authenticationScheme)
{
if (Options.AutomaticAuthentication && string.Equals(AuthenticationManager.AutomaticScheme, authenticationScheme, StringComparison.Ordinal))
{
return true;
}
return Options.AuthenticationDescriptions.Any(description => string.Equals(description.AuthenticationScheme, authenticationScheme, StringComparison.Ordinal));
}
} }
} }

View File

@ -2,15 +2,14 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization; using System.Linq;
using System.Security.Principal;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Features; using Microsoft.AspNetCore.Http.Features;
using Microsoft.AspNetCore.Http.Features.Authentication;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
@ -19,7 +18,8 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
{ {
public class IISMiddleware public class IISMiddleware
{ {
private const string MSAspNetCoreWinAuthToken = "MS-ASPNETCORE-WINAUTHTOKEN"; public static readonly string AuthenticationScheme = "Windows";
private const string MSAspNetCoreClientCert = "MS-ASPNETCORE-CLIENTCERT"; private const string MSAspNetCoreClientCert = "MS-ASPNETCORE-CLIENTCERT";
private const string MSAspNetCoreToken = "MS-ASPNETCORE-TOKEN"; private const string MSAspNetCoreToken = "MS-ASPNETCORE-TOKEN";
@ -28,7 +28,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly string _pairingToken; private readonly string _pairingToken;
public IISMiddleware(RequestDelegate next, ILoggerFactory loggerFactory, IOptions<IISOptions> options, string pairingToken) public IISMiddleware(RequestDelegate next, ILoggerFactory loggerFactory, IOptions<IISOptions> options, string pairingToken, IAuthenticationSchemeProvider authentication)
{ {
if (next == null) if (next == null)
{ {
@ -49,6 +49,13 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
_next = next; _next = next;
_options = options.Value; _options = options.Value;
if (_options.ForwardWindowsAuthentication)
{
authentication.AddScheme(new AuthenticationScheme(AuthenticationScheme, displayName: null, handlerType: typeof(AuthenticationHandler)));
}
_pairingToken = pairingToken; _pairingToken = pairingToken;
_logger = loggerFactory.CreateLogger<IISMiddleware>(); _logger = loggerFactory.CreateLogger<IISMiddleware>();
} }
@ -80,80 +87,14 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
if (_options.ForwardWindowsAuthentication) if (_options.ForwardWindowsAuthentication)
{ {
var winPrincipal = UpdateUser(httpContext); var result = await httpContext.AuthenticateAsync(AuthenticationScheme);
var handler = new AuthenticationHandler(httpContext, _options, winPrincipal); if (result.Succeeded)
AttachAuthenticationHandler(handler);
try
{ {
await _next(httpContext); httpContext.User = result.Principal;
}
finally
{
DetachAuthenticationhandler(handler);
} }
} }
else
{
await _next(httpContext); await _next(httpContext);
} }
} }
private WindowsPrincipal UpdateUser(HttpContext httpContext)
{
var tokenHeader = httpContext.Request.Headers[MSAspNetCoreWinAuthToken];
int hexHandle;
WindowsPrincipal winPrincipal = null;
if (!StringValues.IsNullOrEmpty(tokenHeader)
&& int.TryParse(tokenHeader, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out hexHandle))
{
// Always create the identity if the handle exists, we need to dispose it so it does not leak.
var handle = new IntPtr(hexHandle);
var winIdentity = new WindowsIdentity(handle);
// WindowsIdentity just duplicated the handle so we need to close the original.
NativeMethods.CloseHandle(handle);
httpContext.Response.RegisterForDispose(winIdentity);
winPrincipal = new WindowsPrincipal(winIdentity);
if (_options.AutomaticAuthentication)
{
// Don't get it from httpContext.User, that always returns a non-null anonymous user by default.
var existingPrincipal = httpContext.Features.Get<IHttpAuthenticationFeature>()?.User;
if (existingPrincipal != null)
{
httpContext.User = SecurityHelper.MergeUserPrincipal(existingPrincipal, winPrincipal);
}
else
{
httpContext.User = winPrincipal;
}
}
}
return winPrincipal;
}
private void AttachAuthenticationHandler(AuthenticationHandler handler)
{
var auth = handler.HttpContext.Features.Get<IHttpAuthenticationFeature>();
if (auth == null)
{
auth = new HttpAuthenticationFeature();
handler.HttpContext.Features.Set(auth);
}
handler.PriorHandler = auth.Handler;
auth.Handler = handler;
}
private void DetachAuthenticationhandler(AuthenticationHandler handler)
{
var auth = handler.HttpContext.Features.Get<IHttpAuthenticationFeature>();
if (auth != null)
{
auth.Handler = handler.PriorHandler;
}
}
}
} }

View File

@ -1,21 +1,10 @@
// 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Generic;
using Microsoft.AspNetCore.Http.Authentication;
using Microsoft.AspNetCore.Server.IISIntegration;
namespace Microsoft.AspNetCore.Builder namespace Microsoft.AspNetCore.Builder
{ {
public class IISOptions public class IISOptions
{ {
/// <summary>
/// If true the authentication middleware alter the request user coming in and respond to generic challenges.
/// If false the authentication middleware will only provide identity and respond to challenges when explicitly indicated
/// by the AuthenticationScheme.
/// </summary>
public bool AutomaticAuthentication { get; set; } = true;
/// <summary> /// <summary>
/// If true authentication middleware will try to authenticate using platform handler windows authentication /// If true authentication middleware will try to authenticate using platform handler windows authentication
/// If false authentication middleware won't be added /// If false authentication middleware won't be added
@ -26,20 +15,5 @@ namespace Microsoft.AspNetCore.Builder
/// Populates the ITLSConnectionFeature if the MS-ASPNETCORE-CLIENTCERT request header is present. /// Populates the ITLSConnectionFeature if the MS-ASPNETCORE-CLIENTCERT request header is present.
/// </summary> /// </summary>
public bool ForwardClientCertificate { get; set; } = true; public bool ForwardClientCertificate { get; set; } = true;
/// <summary>
/// Additional information about the authentication type which is made available to the application.
/// </summary>
public IList<AuthenticationDescription> AuthenticationDescriptions { get; } = new List<AuthenticationDescription>()
{
new AuthenticationDescription()
{
AuthenticationScheme = IISDefaults.Negotiate
},
new AuthenticationDescription()
{
AuthenticationScheme = IISDefaults.Ntlm
}
};
} }
} }

View File

@ -11,6 +11,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.Core" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(AspNetCoreVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Hosting.Abstractions" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="$(AspNetCoreVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Http" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="$(AspNetCoreVersion)" /> <PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="$(AspNetCoreVersion)" />

View File

@ -1,7 +1,8 @@
// 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpOverrides; using Microsoft.AspNetCore.HttpOverrides;
@ -58,6 +59,7 @@ namespace Microsoft.AspNetCore.Hosting
{ {
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
}); });
services.AddAuthenticationCore();
}); });
} }

View File

@ -24,7 +24,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
[ConditionalTheory] [ConditionalTheory]
[OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)] [OSSkipCondition(OperatingSystems.Linux | OperatingSystems.MacOSX)]
[InlineData(RuntimeArchitecture.x64, ApplicationType.Portable, Skip = "https://github.com/aspnet/ServerTests/issues/82")] [InlineData(RuntimeArchitecture.x64, ApplicationType.Portable)]
public Task NtlmAuthentication(RuntimeArchitecture architecture, ApplicationType applicationType) public Task NtlmAuthentication(RuntimeArchitecture architecture, ApplicationType applicationType)
{ {
return NtlmAuthentication(ServerType.IISExpress, architecture, applicationType); return NtlmAuthentication(ServerType.IISExpress, architecture, applicationType);
@ -76,6 +76,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Anonymous?True", responseText); Assert.Equal("Anonymous?True", responseText);
/* Disabled for due to https://github.com/aspnet/ServerTests/issues/82
response = await httpClient.GetAsync("/Restricted"); response = await httpClient.GetAsync("/Restricted");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode); Assert.Equal(HttpStatusCode.Unauthorized, response.StatusCode);
@ -92,6 +93,7 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
response = await httpClient.GetAsync("/Forbidden"); response = await httpClient.GetAsync("/Forbidden");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);
*/
var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true }; var httpClientHandler = new HttpClientHandler() { UseDefaultCredentials = true };
httpClient = deploymentResult.CreateHttpClient(httpClientHandler); httpClient = deploymentResult.CreateHttpClient(httpClientHandler);
@ -101,6 +103,11 @@ namespace Microsoft.AspNetCore.Server.IISIntegration.FunctionalTests
Assert.Equal(HttpStatusCode.OK, response.StatusCode); Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("Anonymous?True", responseText); Assert.Equal("Anonymous?True", responseText);
response = await httpClient.GetAsync("/Restricted");
responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.NotEmpty(responseText);
response = await httpClient.GetAsync("/AutoForbid"); response = await httpClient.GetAsync("/AutoForbid");
responseText = await response.Content.ReadAsStringAsync(); responseText = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode); Assert.Equal(HttpStatusCode.Forbidden, response.StatusCode);

View File

@ -1,9 +1,10 @@
// 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http.Features.Authentication; using Microsoft.AspNetCore.Http.Features.Authentication;
@ -152,13 +153,14 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
.UseIISIntegration() .UseIISIntegration()
.Configure(app => .Configure(app =>
{ {
app.Run(context => app.Run(async context =>
{ {
var auth = context.Features.Get<IHttpAuthenticationFeature>(); var auth = context.RequestServices.GetRequiredService<IAuthenticationSchemeProvider>();
Assert.NotNull(auth); var windows = await auth.GetSchemeAsync(IISMiddleware.AuthenticationScheme);
Assert.Equal("Microsoft.AspNetCore.Server.IISIntegration.AuthenticationHandler", auth.Handler.GetType().FullName); Assert.NotNull(windows);
Assert.Null(windows.DisplayName);
Assert.Equal("Microsoft.AspNetCore.Server.IISIntegration.AuthenticationHandler", windows.HandlerType.FullName);
assertsExecuted = true; assertsExecuted = true;
return Task.FromResult(0);
}); });
}); });
var server = new TestServer(builder); var server = new TestServer(builder);
@ -170,8 +172,10 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
Assert.True(assertsExecuted); Assert.True(assertsExecuted);
} }
[Fact] [Theory]
public async Task DoesNotAddAuthenticationHandlerIfWindowsAuthDisabled() [InlineData(true)]
[InlineData(false)]
public async Task OnlyAddAuthenticationHandlerIfForwardWindowsAuthentication(bool forward)
{ {
var assertsExecuted = false; var assertsExecuted = false;
@ -184,15 +188,61 @@ namespace Microsoft.AspNetCore.Server.IISIntegration
{ {
services.Configure<IISOptions>(options => services.Configure<IISOptions>(options =>
{ {
options.ForwardWindowsAuthentication = false; options.ForwardWindowsAuthentication = forward;
});
})
.Configure(app =>
{
app.Run(async context =>
{
var auth = context.RequestServices.GetService<IAuthenticationSchemeProvider>();
Assert.NotNull(auth);
var windowsAuth = await auth.GetSchemeAsync(IISMiddleware.AuthenticationScheme);
if (forward)
{
Assert.NotNull(windowsAuth);
Assert.Null(windowsAuth.DisplayName);
Assert.Equal("AuthenticationHandler", windowsAuth.HandlerType.Name);
}
else
{
Assert.Null(windowsAuth);
}
assertsExecuted = true;
});
});
var server = new TestServer(builder);
var req = new HttpRequestMessage(HttpMethod.Get, "");
req.Headers.TryAddWithoutValidation("MS-ASPNETCORE-TOKEN", "TestToken");
await server.CreateClient().SendAsync(req);
Assert.True(assertsExecuted);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task DoesNotBlowUpWithoutAuth(bool forward)
{
var assertsExecuted = false;
var builder = new WebHostBuilder()
.UseSetting("TOKEN", "TestToken")
.UseSetting("PORT", "12345")
.UseSetting("APPL_PATH", "/")
.UseIISIntegration()
.ConfigureServices(services =>
{
services.Configure<IISOptions>(options =>
{
options.ForwardWindowsAuthentication = forward;
}); });
}) })
.Configure(app => .Configure(app =>
{ {
app.Run(context => app.Run(context =>
{ {
var auth = context.Features.Get<IHttpAuthenticationFeature>();
Assert.Null(auth);
assertsExecuted = true; assertsExecuted = true;
return Task.FromResult(0); return Task.FromResult(0);
}); });

View File

@ -11,6 +11,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="$(AspNetCoreVersion)" /> <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="$(AspNetCoreVersion)" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="$(TestSdkVersion)" />
<PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" /> <PackageReference Include="xunit.runner.visualstudio" Version="$(XunitVersion)" />

View File

@ -1,11 +1,12 @@
// 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System;
using System.Security.Principal; using System.Security.Principal;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Authentication; using Microsoft.AspNetCore.Server.IISIntegration;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Xunit; using Xunit;
@ -51,30 +52,18 @@ namespace TestSites
} }
else else
{ {
return context.Authentication.ChallengeAsync(); return context.ChallengeAsync();
} }
} }
if (context.Request.Path.Equals("/Forbidden")) if (context.Request.Path.Equals("/Forbidden"))
{ {
return context.Authentication.ForbidAsync(AuthenticationManager.AutomaticScheme); return context.ForbidAsync();
} }
if (context.Request.Path.Equals("/AutoForbid")) if (context.Request.Path.Equals("/AutoForbid"))
{ {
return context.Authentication.ChallengeAsync(); return context.ChallengeAsync();
}
if (context.Request.Path.Equals("/RestrictedNegotiate"))
{
if (string.Equals("Negotiate", context.User.Identity.AuthenticationType, StringComparison.Ordinal))
{
return context.Response.WriteAsync("Negotiate");
}
else
{
return context.Authentication.ChallengeAsync("Negotiate");
}
} }
if (context.Request.Path.Equals("/RestrictedNTLM")) if (context.Request.Path.Equals("/RestrictedNTLM"))
@ -85,7 +74,7 @@ namespace TestSites
} }
else else
{ {
return context.Authentication.ChallengeAsync("NTLM"); return context.ChallengeAsync(IISMiddleware.AuthenticationScheme);
} }
} }