protected override async Task <AuthenticateResult> HandleAuthenticateAsync() { // You only get client certificates over HTTPS if (!Context.Request.IsHttps) { Logger.NotHttps(); return(AuthenticateResult.NoResult()); } try { 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.NoCertificate(); return(AuthenticateResult.NoResult()); } if (_cache != null) { var cacheHit = _cache.Get(Context, clientCertificate); if (cacheHit != null) { return(cacheHit); } } var result = await ValidateCertificateAsync(clientCertificate); if (_cache != null) { _cache.Put(Context, clientCertificate, result); } return(result); } catch (Exception ex) { var authenticationFailedContext = new CertificateAuthenticationFailedContext(Context, Scheme, Options) { Exception = ex }; await Events.AuthenticationFailed(authenticationFailedContext); if (authenticationFailedContext.Result != null) { return(authenticationFailedContext.Result); } throw; } }
private async Task <CertificateAuthenticationFailedContext> HandleFailureAsync(Exception error) { var authenticationFailedContext = new CertificateAuthenticationFailedContext(Context, Scheme, Options) { Exception = error }; await Events.AuthenticationFailed(authenticationFailedContext); return(authenticationFailedContext); }
protected override async Task <AuthenticateResult> HandleAuthenticateAsync() { // You only get client certificates over HTTPS if (!Context.Request.IsHttps) { return(AuthenticateResult.NoResult()); } try { 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.NoCertificate(); 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.CertificateRejected("Self signed", 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.CertificateRejected("Chained", clientCertificate.Subject); return(AuthenticateResult.Fail("Options do not allow chained certificates.")); } var chainPolicy = BuildChainPolicy(clientCertificate); var chain = new X509Chain { ChainPolicy = chainPolicy }; var certificateIsValid = chain.Build(clientCertificate); if (!certificateIsValid) { var chainErrors = new List <string>(); foreach (var validationFailure in chain.ChainStatus) { chainErrors.Add($"{validationFailure.Status} {validationFailure.StatusInformation}"); } Logger.CertificateFailedValidation(clientCertificate.Subject, chainErrors); return(AuthenticateResult.Fail("Client certificate failed validation.")); } var certificateValidatedContext = new CertificateValidatedContext(Context, Scheme, Options) { ClientCertificate = clientCertificate, Principal = CreatePrincipal(clientCertificate) }; await Events.CertificateValidated(certificateValidatedContext); if (certificateValidatedContext.Result != null) { return(certificateValidatedContext.Result); } certificateValidatedContext.Success(); return(certificateValidatedContext.Result); } catch (Exception ex) { var authenticationFailedContext = new CertificateAuthenticationFailedContext(Context, Scheme, Options) { Exception = ex }; await Events.AuthenticationFailed(authenticationFailedContext); if (authenticationFailedContext.Result != null) { return(authenticationFailedContext.Result); } throw; } }
/// <summary> /// Invoked when a certificate fails authentication. /// </summary> /// <param name="context"></param> /// <returns></returns> public virtual Task AuthenticationFailed(CertificateAuthenticationFailedContext context) => OnAuthenticationFailed(context);