Is it possible (and if so, how?) to configure a self hosted owin endpoint to use client certificate mapping authentication with A/D? IIS has this feature link, but so far I have not found an equivalent for self-hosted endpoints.
The way in which I have gotten this to work though (bearing in mind this approach is probably not 100% foolproof), is a 2-step process by using a combination of authenticationSchemeSelectorDelegate and OWIN.
This will choose the appropriate AuthenticationScheme (allowing requests containing a cert through, otherwise deferring to NTLM authentication)
public void Configuration(IAppBuilder appBuilder)
{
var listener = (HttpListener)appBuilder.Properties[typeof(HttpListener).FullName];
listener.AuthenticationSchemeSelectorDelegate += AuthenticationSchemeSelectorDelegate;
}
private AuthenticationSchemes AuthenticationSchemeSelectorDelegate(HttpListenerRequest httpRequest)
{
if (!httpRequest.IsSecureConnection) return AuthenticationSchemes.Ntlm;
var clientCert = httpRequest.GetClientCertificate();
if (clientCert == null) return AuthenticationSchemes.Ntlm;
else return AuthenticationSchemes.Anonymous;
}
This will read the contents of the cert and populate the "server.User" environment variable accordingly
public class CertificateAuthenticator
{
readonly Func<IDictionary<string, object>, Task> _appFunc;
public CertificateAuthenticator(Func<IDictionary<string, object>, Task> appFunc)
{
_appFunc = appFunc;
}
public Task Invoke(IDictionary<string, object> environment)
{
// Are we authenticated already (NTLM)
var user = environment["server.User"] as IPrincipal;
if (user != null && user.Identity.IsAuthenticated) return _appFunc.Invoke(environment);
var context = environment["System.Net.HttpListenerContext"] as HttpListenerContext;
if (context == null) return _appFunc.Invoke(environment);
var clientCertificate = context.Request.GetClientCertificate();
// Parse out username from certificate
var identity = new GenericPrincipal
(
new GenericIdentity(username), new string[0]
);
environment["server.User"] = identity;
}
}
Is there not a better/standardized way?
Client Certificate Mapping authentication using Active Directory - this method of authentication requires that the IIS 7 server and the client computer are members of an Active Directory domain, and user accounts are stored in Active Directory.
On the taskbar, click Start, and then click Control Panel. In Control Panel, click Programs and Features, and then click Turn Windows Features on or off. Expand Internet Information Services, then select Client Certificate Mapping Authentication, and then click OK.
I have not seen any standard components built for this yet. That said, it should be possible to clean up your code a little:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With