#27 Forward client certificates.

This commit is contained in:
Chris R 2016-01-13 15:07:14 -08:00
parent b2a3f871c0
commit cc1cb1d480
5 changed files with 87 additions and 1 deletions

View File

@ -26,10 +26,15 @@ namespace IISSample
await context.Response.WriteAsync("User - " + context.User.Identity.Name + Environment.NewLine);
await context.Response.WriteAsync("PathBase: " + context.Request.PathBase.Value + Environment.NewLine);
await context.Response.WriteAsync("Path: " + context.Request.Path.Value + Environment.NewLine);
await context.Response.WriteAsync("ClientCert: " + context.Connection.ClientCertificate + Environment.NewLine);
await context.Response.WriteAsync(Environment.NewLine + "Headers:" + Environment.NewLine);
foreach (var header in context.Request.Headers)
{
await context.Response.WriteAsync(header.Key + ": " + header.Value + Environment.NewLine);
}
await context.Response.WriteAsync(Environment.NewLine + "Environment Variables:" + Environment.NewLine);
var vars = Environment.GetEnvironmentVariables();
foreach (var key in vars.Keys)
{

View File

@ -0,0 +1,56 @@
// 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.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.Http.Features;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
namespace Microsoft.AspNet.IISPlatformHandler
{
internal class ForwardedTlsConnectionFeature : ITlsConnectionFeature
{
private StringValues _header;
private X509Certificate2 _certificate;
private ILogger _logger;
public ForwardedTlsConnectionFeature(ILogger logger, StringValues header)
{
_logger = logger;
_header = header;
}
public X509Certificate2 ClientCertificate
{
get
{
if (_certificate == null && _header != StringValues.Empty)
{
try
{
var bytes = Convert.FromBase64String(_header);
_certificate = new X509Certificate2(bytes);
}
catch (Exception ex)
{
_logger.LogWarning("Failed to read the client certificate.", ex);
}
}
return _certificate;
}
set
{
_certificate = value;
_header = StringValues.Empty;
}
}
public Task<X509Certificate2> GetClientCertificateAsync(CancellationToken cancellationToken)
{
return Task.FromResult(ClientCertificate);
}
}
}

View File

@ -3,13 +3,16 @@
using System;
using System.Globalization;
using System.Security.Cryptography.X509Certificates;
using System.Security.Principal;
using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Http.Features;
using Microsoft.AspNet.Http.Features.Authentication;
using Microsoft.AspNet.Http.Features.Authentication.Internal;
using Microsoft.Extensions.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Microsoft.Extensions.Primitives;
@ -18,16 +21,22 @@ namespace Microsoft.AspNet.IISPlatformHandler
public class IISPlatformHandlerMiddleware
{
private const string XIISWindowsAuthToken = "X-IIS-WindowsAuthToken";
private const string MSPlatformHandlerClientCert = "MS-PLATFORM-HANDLER-CLIENTCERT";
private readonly RequestDelegate _next;
private readonly IISPlatformHandlerOptions _options;
private readonly ILogger _logger;
public IISPlatformHandlerMiddleware(RequestDelegate next, IOptions<IISPlatformHandlerOptions> options)
public IISPlatformHandlerMiddleware(RequestDelegate next, ILoggerFactory loggerFactory, IOptions<IISPlatformHandlerOptions> options)
{
if (next == null)
{
throw new ArgumentNullException(nameof(next));
}
if (loggerFactory == null)
{
throw new ArgumentNullException(nameof(loggerFactory));
}
if (options == null)
{
throw new ArgumentNullException(nameof(options));
@ -35,10 +44,20 @@ namespace Microsoft.AspNet.IISPlatformHandler
_next = next;
_options = options.Value;
_logger = loggerFactory.CreateLogger<IISPlatformHandlerMiddleware>();
}
public async Task Invoke(HttpContext httpContext)
{
if (_options.FlowClientCertificate)
{
var header = httpContext.Request.Headers[MSPlatformHandlerClientCert];
if (!StringValues.IsNullOrEmpty(header))
{
httpContext.Features.Set<ITlsConnectionFeature>(new ForwardedTlsConnectionFeature(_logger, header));
}
}
if (_options.FlowWindowsAuthentication)
{
var winPrincipal = UpdateUser(httpContext);

View File

@ -22,6 +22,11 @@ namespace Microsoft.AspNet.Builder
/// </summary>
public bool FlowWindowsAuthentication { get; set; } = true;
/// <summary>
/// Populates the ITLSConnectionFeature if the MS-PLATFORM-HANDLER-CLIENTCERT request header is present.
/// </summary>
public bool FlowClientCertificate { get; set; } = true;
/// <summary>
/// Additional information about the authentication type which is made available to the application.
/// </summary>

View File

@ -13,6 +13,7 @@
"Microsoft.AspNet.Hosting.Abstractions": "1.0.0-*",
"Microsoft.AspNet.Http": "1.0.0-*",
"Microsoft.AspNet.Http.Extensions": "1.0.0-*",
"Microsoft.Extensions.Logging.Abstractions": "1.0.0-*",
"Microsoft.Extensions.Options": "1.0.0-*",
"Microsoft.Extensions.SecurityHelper.Sources": {
"type": "build",