aspnetcore/src/Microsoft.AspNetCore.Server.../AuthenticationHandler.cs

93 lines
3.1 KiB
C#

// 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.Security.Claims;
using System.Globalization;
using System.Security.Principal;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNetCore.Server.IISIntegration
{
internal class AuthenticationHandler : IAuthenticationHandler
{
private const string MSAspNetCoreWinAuthToken = "MS-ASPNETCORE-WINAUTHTOKEN";
private WindowsPrincipal _user;
private HttpContext _context;
internal AuthenticationScheme Scheme { get; private set; }
public Task<AuthenticateResult> AuthenticateAsync()
{
var user = GetUser();
if (user != null)
{
return Task.FromResult(AuthenticateResult.Success(new AuthenticationTicket(user, Scheme.Name)));
}
else
{
return Task.FromResult(AuthenticateResult.None());
}
}
private WindowsPrincipal GetUser()
{
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 _user;
}
public Task ChallengeAsync(AuthenticationProperties properties)
{
// We would normally set the www-authenticate header here, but IIS does that for us.
_context.Response.StatusCode = 401;
return TaskCache.CompletedTask;
}
public Task ForbidAsync(AuthenticationProperties properties)
{
_context.Response.StatusCode = 403;
return TaskCache.CompletedTask;
}
public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
{
Scheme = scheme;
_context = context;
return TaskCache.CompletedTask;
}
public Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
{
throw new NotSupportedException();
}
public Task SignOutAsync(AuthenticationProperties properties)
{
return TaskCache.CompletedTask;
}
}
}