Beispiel #1
0
        private async Task <AuthenticateResult> ValidateCertificateAsync(X509Certificate2 clientCertificate)
        {
            // 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);

            using var chain = new X509Chain
                  {
                      ChainPolicy = chainPolicy
                  };

            var certificateIsValid = chain.Build(clientCertificate);

            if (!certificateIsValid)
            {
                var chainErrors = new List <string>(chain.ChainStatus.Length);
                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 !);
        }
Beispiel #2
0
        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;
            }
        }
Beispiel #3
0
 /// <summary>
 /// Invoked after a certificate has been validated
 /// </summary>
 /// <param name="context"></param>
 /// <returns></returns>
 public virtual Task CertificateValidated(CertificateValidatedContext context) => OnCertificateValidated(context);