I am looking for some help using X509 client certificates to authenticate users. We are required to remove the username password from login page and force login using User SmartCards. I have found a certificate handler that creates a claim based off X500DistinguishedName but I am having trouble matching it to a User Claims Principal. In your opinion, what would be the best way to achieve this login requirement? I have been reading about using the client certificate to sign the JwtBearer token but have not found a sample that works with authenticating a user.
handler.... { internal class ClientCertificateHandler : AuthenticationHandler<CertficateAuthenticationOptions> { protected override Task<AuthenticateResult> HandleAuthenticateAsync() { var certificate = Context.Connection.ClientCertificate; #if NET451 if (certificate != null && certificate.Verify()) #else if (certificate != null) #endif { var roles = GetRolesFromFirstMatchingCertificate(certificate); if (roles?.Length > 0) { var claims = new List<Claim>(); foreach (var role in roles) { claims.Add(new Claim(ClaimTypes.X500DistinguishedName, role)); }
var userIdentity = new ClaimsIdentity(claims, Options.AuthenticationScheme);
var userPrincipal = new ClaimsPrincipal(userIdentity);
var ticket = new AuthenticationTicket(userPrincipal, new AuthenticationProperties(), Options.AuthenticationScheme);
return Task.FromResult(AuthenticateResult.Success(ticket));
}
}
return Task.FromResult(AuthenticateResult.Skip());
}
private string[] GetRolesFromFirstMatchingCertificate(X509Certificate2 certificate)
{
var roles = (Options.CertificatesAndRoles
.Where(r => r.Issuer == certificate.Issuer && r.Subject == certificate.Subject)
.Select(r => r.Roles)).FirstOrDefault();
return roles;
}
}