protected override async Task <AuthenticateResult> HandleAuthenticateAsync() { // You only get client certificates over HTTPS if (!Context.Request.IsHttps) { return(AuthenticateResult.NoResult()); } var clientCertificate = await Context.Connection.GetClientCertificateAsync(); // This should never be the case, as cert authentication happens long before ASP.NET kicks in. if (clientCertificate == null) { Logger.LogDebug("No client certificate found."); return(AuthenticateResult.NoResult()); } // If we have a self signed cert, and they're not allowed, exit early and not bother with // any other validations. if (clientCertificate.IsSelfSigned() && !Options.AllowedCertificateTypes.HasFlag(CertificateTypes.SelfSigned)) { Logger.LogWarning("Self signed certificate rejected, subject was {0}", clientCertificate.Subject); return(AuthenticateResult.Fail("Options do not allow self signed certificates.")); } // If we have a chained cert, and they're not allowed, exit early and not bother with // any other validations. if (!clientCertificate.IsSelfSigned() && !Options.AllowedCertificateTypes.HasFlag(CertificateTypes.Chained)) { Logger.LogWarning("Chained certificate rejected, subject was {0}", clientCertificate.Subject); return(AuthenticateResult.Fail("Options do not allow chained certificates.")); } var chainPolicy = BuildChainPolicy(clientCertificate); try { var chain = new X509Chain { ChainPolicy = chainPolicy }; var certificateIsValid = chain.Build(clientCertificate); if (!certificateIsValid) { using (Logger.BeginScope(clientCertificate.SHA256Thumprint())) { Logger.LogWarning("Client certificate failed validation, subject was {0}", clientCertificate.Subject); foreach (var validationFailure in chain.ChainStatus) { Logger.LogWarning("{0} {1}", validationFailure.Status, validationFailure.StatusInformation); } } return(AuthenticateResult.Fail("Client certificate failed validation.")); } var validateCertificateContext = new ValidateCertificateContext(Context, Scheme, Options) { ClientCertificate = clientCertificate }; await Events.ValidateCertificate(validateCertificateContext); if (validateCertificateContext.Result != null && validateCertificateContext.Result.Succeeded) { var ticket = new AuthenticationTicket(validateCertificateContext.Principal, Scheme.Name); return(AuthenticateResult.Success(ticket)); } if (validateCertificateContext.Result != null && validateCertificateContext.Result.Failure != null) { return(AuthenticateResult.Fail(validateCertificateContext.Result.Failure)); } return(AuthenticateResult.NoResult()); } catch (Exception ex) { var authenticationFailedContext = new CertificateAuthenticationFailedContext(Context, Scheme, Options) { Exception = ex }; await Events.AuthenticationFailed(authenticationFailedContext); if (authenticationFailedContext.Result != null) { return(authenticationFailedContext.Result); } throw; } }
public virtual Task ValidateCertificate(ValidateCertificateContext context) => OnValidateCertificate(context);