Skip to content
This repository has been archived by the owner on Nov 1, 2018. It is now read-only.

Commit

Permalink
#27 Forward client certificates.
Browse files Browse the repository at this point in the history
  • Loading branch information
Tratcher committed Jan 13, 2016
1 parent b2a3f87 commit bbdcfa7
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 1 deletion.
7 changes: 7 additions & 0 deletions samples/IISSample/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,23 @@ public void Configure(IApplicationBuilder app, ILoggerFactory loggerfactory)
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)
{
var value = vars[key];
await context.Response.WriteAsync(key + ": " + value + Environment.NewLine);
}
// throw new Exception("Test Exception");
});
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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 apply the client certificate.", ex);
}
}
return _certificate;
}
set
{
_certificate = value;
_header = StringValues.Empty;
}
}

public Task<X509Certificate2> GetClientCertificateAsync(CancellationToken cancellationToken)
{
return Task.FromResult(ClientCertificate);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -18,27 +21,43 @@ 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));
}

_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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public class IISPlatformHandlerOptions
/// </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>
Expand Down
1 change: 1 addition & 0 deletions src/Microsoft.AspNet.IISPlatformHandler/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit bbdcfa7

Please sign in to comment.