diff --git a/src/Microsoft.AspNet.Authentication.JwtBearer/JwtBearerAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication.JwtBearer/JwtBearerAuthenticationMiddleware.cs index 1cd69a7656..1127f12889 100644 --- a/src/Microsoft.AspNet.Authentication.JwtBearer/JwtBearerAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication.JwtBearer/JwtBearerAuthenticationMiddleware.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Diagnostics.CodeAnalysis; using System.Net.Http; using Microsoft.AspNet.Builder; using Microsoft.Framework.Internal; @@ -63,7 +62,7 @@ namespace Microsoft.AspNet.Authentication.JwtBearer Options.MetadataAddress += ".well-known/openid-configuration"; } - var httpClient = new HttpClient(ResolveHttpMessageHandler(Options)); + var httpClient = new HttpClient(Options.BackchannelHttpHandler ?? new HttpClientHandler()); httpClient.Timeout = Options.BackchannelTimeout; httpClient.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB @@ -80,28 +79,5 @@ namespace Microsoft.AspNet.Authentication.JwtBearer { return new JwtBearerAuthenticationHandler(); } - - [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")] - private static HttpMessageHandler ResolveHttpMessageHandler(JwtBearerAuthenticationOptions options) - { - HttpMessageHandler handler = options.BackchannelHttpHandler ?? -#if DNX451 - new WebRequestHandler(); - // If they provided a validator, apply it or fail. - if (options.BackchannelCertificateValidator != null) - { - // Set the cert validate callback - var webRequestHandler = handler as WebRequestHandler; - if (webRequestHandler == null) - { - throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch); - } - webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate; - } -#else - new HttpClientHandler(); -#endif - return handler; - } } } diff --git a/src/Microsoft.AspNet.Authentication.JwtBearer/JwtBearerAuthenticationOptions.cs b/src/Microsoft.AspNet.Authentication.JwtBearer/JwtBearerAuthenticationOptions.cs index 373095f822..6e778907bf 100644 --- a/src/Microsoft.AspNet.Authentication.JwtBearer/JwtBearerAuthenticationOptions.cs +++ b/src/Microsoft.AspNet.Authentication.JwtBearer/JwtBearerAuthenticationOptions.cs @@ -66,18 +66,6 @@ namespace Microsoft.AspNet.Authentication.JwtBearer /// public TimeSpan BackchannelTimeout { get; set; } = TimeSpan.FromMinutes(1); -#if DNX451 - /// - /// Gets or sets the a pinned certificate validator to use to validate the endpoints used - /// when retrieving metadata. - /// - /// - /// The pinned certificate validator. - /// - /// If this property is null then the default certificate checks are performed, - /// validating the subject name and if the signing chain is a trusted party. - public ICertificateValidator BackchannelCertificateValidator { get; set; } -#endif /// /// Configuration provided directly by the developer. If provided, then MetadataAddress and the Backchannel properties /// will not be used. This information should not be updated during request processing. diff --git a/src/Microsoft.AspNet.Authentication.JwtBearer/project.json b/src/Microsoft.AspNet.Authentication.JwtBearer/project.json index 97fbbb5e5d..f92c6b6f4a 100644 --- a/src/Microsoft.AspNet.Authentication.JwtBearer/project.json +++ b/src/Microsoft.AspNet.Authentication.JwtBearer/project.json @@ -13,7 +13,6 @@ "frameworks": { "dnx451": { "frameworkAssemblies": { - "System.Net.Http.WebRequest": "", "System.Net.Http": "" } }, diff --git a/src/Microsoft.AspNet.Authentication.OAuth/OAuthAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication.OAuth/OAuthAuthenticationMiddleware.cs index 1b71de47b4..b38637b8aa 100644 --- a/src/Microsoft.AspNet.Authentication.OAuth/OAuthAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication.OAuth/OAuthAuthenticationMiddleware.cs @@ -75,7 +75,7 @@ namespace Microsoft.AspNet.Authentication.OAuth Options.StateDataFormat = new PropertiesDataFormat(dataProtector); } - Backchannel = new HttpClient(ResolveHttpMessageHandler(Options)); + Backchannel = new HttpClient(Options.BackchannelHttpHandler ?? new HttpClientHandler()); Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET OAuth middleware"); Backchannel.Timeout = Options.BackchannelTimeout; Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB @@ -96,28 +96,5 @@ namespace Microsoft.AspNet.Authentication.OAuth { return new OAuthAuthenticationHandler(Backchannel); } - - [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")] - private static HttpMessageHandler ResolveHttpMessageHandler(OAuthAuthenticationOptions options) - { - HttpMessageHandler handler = options.BackchannelHttpHandler ?? -#if DNX451 - new WebRequestHandler(); - // If they provided a validator, apply it or fail. - if (options.BackchannelCertificateValidator != null) - { - // Set the cert validate callback - var webRequestHandler = handler as WebRequestHandler; - if (webRequestHandler == null) - { - throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch); - } - webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate; - } -#else - new HttpClientHandler(); -#endif - return handler; - } } } diff --git a/src/Microsoft.AspNet.Authentication.OAuth/OAuthAuthenticationOptions.cs b/src/Microsoft.AspNet.Authentication.OAuth/OAuthAuthenticationOptions.cs index 680947e36a..58749deed8 100644 --- a/src/Microsoft.AspNet.Authentication.OAuth/OAuthAuthenticationOptions.cs +++ b/src/Microsoft.AspNet.Authentication.OAuth/OAuthAuthenticationOptions.cs @@ -42,19 +42,6 @@ namespace Microsoft.AspNet.Authentication.OAuth /// public string UserInformationEndpoint { get; set; } -#if DNX451 - /// - /// Gets or sets the a pinned certificate validator to use to validate the endpoints used - /// in back channel communications belong to the auth provider. - /// - /// - /// The pinned certificate validator. - /// - /// If this property is null then the default certificate checks are performed, - /// validating the subject name and if the signing chain is a trusted party. - public ICertificateValidator BackchannelCertificateValidator { get; set; } -#endif - /// /// Get or sets the text that the user can display on a sign in user interface. /// diff --git a/src/Microsoft.AspNet.Authentication.OAuth/project.json b/src/Microsoft.AspNet.Authentication.OAuth/project.json index 5dc4078287..d9d3429cfd 100644 --- a/src/Microsoft.AspNet.Authentication.OAuth/project.json +++ b/src/Microsoft.AspNet.Authentication.OAuth/project.json @@ -13,7 +13,6 @@ "frameworks": { "dnx451": { "frameworkAssemblies": { - "System.Net.Http.WebRequest": "", "System.Net.Http": "" } }, diff --git a/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationMiddleware.cs index 4ed9fb965c..13a3d25562 100644 --- a/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationMiddleware.cs @@ -102,7 +102,7 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect Options.TokenValidationParameters.ValidAudience = Options.ClientId; } - Backchannel = new HttpClient(ResolveHttpMessageHandler(Options)); + Backchannel = new HttpClient(Options.BackchannelHttpHandler ?? new HttpClientHandler()); Backchannel.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET OpenIdConnect middleware"); Backchannel.Timeout = Options.BackchannelTimeout; Backchannel.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB @@ -149,29 +149,6 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect return new OpenIdConnectAuthenticationHandler(Backchannel); } - [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")] - private static HttpMessageHandler ResolveHttpMessageHandler(OpenIdConnectAuthenticationOptions options) - { - var handler = options.BackchannelHttpHandler ?? -#if DNX451 - new WebRequestHandler(); - // If they provided a validator, apply it or fail. - if (options.BackchannelCertificateValidator != null) - { - // Set the cert validate callback - var webRequestHandler = handler as WebRequestHandler; - if (webRequestHandler == null) - { - throw new InvalidOperationException(Resources.OIDCH_0102_Exception_ValidatorHandlerMismatch); - } - webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate; - } -#else - new HttpClientHandler(); -#endif - return handler; - } - private class StringSerializer : IDataSerializer { public string Deserialize(byte[] data) diff --git a/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationOptions.cs b/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationOptions.cs index f24cdec61c..44427e4b5e 100644 --- a/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationOptions.cs +++ b/src/Microsoft.AspNet.Authentication.OpenIdConnect/OpenIdConnectAuthenticationOptions.cs @@ -7,7 +7,6 @@ using System.Diagnostics.CodeAnalysis; using System.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Net.Http; -using System.Security.Claims; using Microsoft.AspNet.Http; using Microsoft.AspNet.Http.Authentication; using Microsoft.Framework.Caching.Distributed; @@ -66,18 +65,6 @@ namespace Microsoft.AspNet.Authentication.OpenIdConnect /// public string Authority { get; set; } -#if DNX451 - /// - /// Gets or sets the a pinned certificate validator to use to validate the endpoints used - /// when retrieving metadata. - /// - /// - /// The pinned certificate validator. - /// - /// If this property is null then the default certificate checks are performed, - /// validating the subject name and if the signing chain is a trusted party. - public ICertificateValidator BackchannelCertificateValidator { get; set; } -#endif /// /// The HttpMessageHandler used to retrieve metadata. /// This cannot be set at the same time as BackchannelCertificateValidator unless the value diff --git a/src/Microsoft.AspNet.Authentication.OpenIdConnect/project.json b/src/Microsoft.AspNet.Authentication.OpenIdConnect/project.json index 3165bdeba1..597b3d5513 100644 --- a/src/Microsoft.AspNet.Authentication.OpenIdConnect/project.json +++ b/src/Microsoft.AspNet.Authentication.OpenIdConnect/project.json @@ -14,8 +14,7 @@ "frameworks": { "dnx451": { "frameworkAssemblies": { - "System.Net.Http": "", - "System.Net.Http.WebRequest": "" + "System.Net.Http": "" } }, "dnxcore50": { diff --git a/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationMiddleware.cs b/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationMiddleware.cs index 1a0d28f736..ae8c118769 100644 --- a/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationMiddleware.cs +++ b/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationMiddleware.cs @@ -74,7 +74,7 @@ namespace Microsoft.AspNet.Authentication.Twitter throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Exception_OptionMustBeProvided, "SignInScheme")); } - _httpClient = new HttpClient(ResolveHttpMessageHandler(Options)); + _httpClient = new HttpClient(Options.BackchannelHttpHandler ?? new HttpClientHandler()); _httpClient.Timeout = Options.BackchannelTimeout; _httpClient.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB _httpClient.DefaultRequestHeaders.Accept.ParseAdd("*/*"); @@ -90,28 +90,5 @@ namespace Microsoft.AspNet.Authentication.Twitter { return new TwitterAuthenticationHandler(_httpClient); } - - [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Managed by caller")] - private static HttpMessageHandler ResolveHttpMessageHandler(TwitterAuthenticationOptions options) - { - var handler = options.BackchannelHttpHandler ?? -#if DNX451 - new WebRequestHandler(); - // If they provided a validator, apply it or fail. - if (options.BackchannelCertificateValidator != null) - { - // Set the cert validate callback - var webRequestHandler = handler as WebRequestHandler; - if (webRequestHandler == null) - { - throw new InvalidOperationException(Resources.Exception_ValidatorHandlerMismatch); - } - webRequestHandler.ServerCertificateValidationCallback = options.BackchannelCertificateValidator.Validate; - } -#else - new HttpClientHandler(); -#endif - return handler; - } } } diff --git a/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationOptions.cs b/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationOptions.cs index cc6d929a99..dd075ea14b 100644 --- a/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationOptions.cs +++ b/src/Microsoft.AspNet.Authentication.Twitter/TwitterAuthenticationOptions.cs @@ -3,7 +3,6 @@ using System; using System.Net.Http; -using System.Security.Claims; using Microsoft.AspNet.Http; namespace Microsoft.AspNet.Authentication.Twitter @@ -22,16 +21,6 @@ namespace Microsoft.AspNet.Authentication.Twitter Caption = AuthenticationScheme; CallbackPath = new PathString("/signin-twitter"); BackchannelTimeout = TimeSpan.FromSeconds(60); -#if DNX451 - // Twitter lists its valid Subject Key Identifiers at https://dev.twitter.com/docs/security/using-ssl - BackchannelCertificateValidator = new CertificateSubjectKeyIdentifierValidator( - new[] - { - "A5EF0B11CEC04103A34A659048B21CE0572D7D47", // VeriSign Class 3 Secure Server CA - G2 - "0D445C165344C1827E1D20AB25F40163D8BE79A5", // VeriSign Class 3 Secure Server CA - G3 - "5F60CF619055DF8443148A602AB2F57AF44318EF", // Symantec Class 3 Secure Server CA - G4 - }); -#endif } /// @@ -53,18 +42,7 @@ namespace Microsoft.AspNet.Authentication.Twitter /// The back channel timeout. /// public TimeSpan BackchannelTimeout { get; set; } -#if DNX451 - /// - /// Gets or sets the a pinned certificate validator to use to validate the endpoints used - /// in back channel communications belong to Twitter. - /// - /// - /// The pinned certificate validator. - /// - /// If this property is null then the default certificate checks are performed, - /// validating the subject name and if the signing chain is a trusted party. - public ICertificateValidator BackchannelCertificateValidator { get; set; } -#endif + /// /// The HttpMessageHandler used to communicate with Twitter. /// This cannot be set at the same time as BackchannelCertificateValidator unless the value diff --git a/src/Microsoft.AspNet.Authentication.Twitter/project.json b/src/Microsoft.AspNet.Authentication.Twitter/project.json index a567a377a8..c0268cc5d0 100644 --- a/src/Microsoft.AspNet.Authentication.Twitter/project.json +++ b/src/Microsoft.AspNet.Authentication.Twitter/project.json @@ -12,7 +12,6 @@ "frameworks": { "dnx451": { "frameworkAssemblies": { - "System.Net.Http.WebRequest": "", "System.Net.Http": "" } }, diff --git a/src/Microsoft.AspNet.Authentication/CertificateSubjectKeyIdentifierValidator.cs b/src/Microsoft.AspNet.Authentication/CertificateSubjectKeyIdentifierValidator.cs deleted file mode 100644 index 4bb78f8d9b..0000000000 --- a/src/Microsoft.AspNet.Authentication/CertificateSubjectKeyIdentifierValidator.cs +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#if DNX451 -using System; -using System.Collections.Generic; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Framework.Internal; - -namespace Microsoft.AspNet.Authentication -{ - /// - /// Provides pinned certificate validation based on the subject key identifier of the certificate. - /// - public class CertificateSubjectKeyIdentifierValidator : ICertificateValidator - { - private readonly HashSet _validSubjectKeyIdentifiers; - - /// - /// Initializes a new instance of the class. - /// - /// A set of subject key identifiers which are valid for an HTTPS request. - public CertificateSubjectKeyIdentifierValidator([NotNull] IEnumerable validSubjectKeyIdentifiers) - { - _validSubjectKeyIdentifiers = new HashSet(validSubjectKeyIdentifiers, StringComparer.OrdinalIgnoreCase); - - if (_validSubjectKeyIdentifiers.Count == 0) - { - throw new ArgumentOutOfRangeException(nameof(validSubjectKeyIdentifiers)); - } - } - - /// - /// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication. - /// - /// An object that contains state information for this validation. - /// The certificate used to authenticate the remote party. - /// The chain of certificate authorities associated with the remote certificate. - /// One or more errors associated with the remote certificate. - /// A Boolean value that determines whether the specified certificate is accepted for authentication. - public bool Validate(object sender, X509Certificate certificate, [NotNull] X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - if (sslPolicyErrors != SslPolicyErrors.None) - { - return false; - } - - if (chain.ChainElements.Count < 2) - { - // Self signed. - return false; - } - - foreach (var chainElement in chain.ChainElements) - { - string subjectKeyIdentifier = GetSubjectKeyIdentifier(chainElement.Certificate); - if (string.IsNullOrEmpty(subjectKeyIdentifier)) - { - continue; - } - - if (_validSubjectKeyIdentifiers.Contains(subjectKeyIdentifier)) - { - return true; - } - } - - return false; - } - - private static string GetSubjectKeyIdentifier(X509Certificate2 certificate) - { - const string SubjectKeyIdentifierOid = "2.5.29.14"; - var extension = certificate.Extensions[SubjectKeyIdentifierOid] as X509SubjectKeyIdentifierExtension; - - return extension == null ? null : extension.SubjectKeyIdentifier; - } - } -} -#endif diff --git a/src/Microsoft.AspNet.Authentication/CertificateSubjectPublicKeyInfoValidator.cs b/src/Microsoft.AspNet.Authentication/CertificateSubjectPublicKeyInfoValidator.cs deleted file mode 100644 index 11e827ae7f..0000000000 --- a/src/Microsoft.AspNet.Authentication/CertificateSubjectPublicKeyInfoValidator.cs +++ /dev/null @@ -1,128 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#if DNX451 -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics.CodeAnalysis; -using System.Net.Security; -using System.Runtime.InteropServices; -using System.Security.Cryptography; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Framework.Internal; -using Microsoft.Win32; - -namespace Microsoft.AspNet.Authentication -{ - /// - /// Implements a cert pinning validator passed on - /// http://datatracker.ietf.org/doc/draft-ietf-websec-key-pinning/?include_text=1 - /// - public class CertificateSubjectPublicKeyInfoValidator : ICertificateValidator - { - private readonly HashSet _validBase64EncodedSubjectPublicKeyInfoHashes; - - private readonly SubjectPublicKeyInfoAlgorithm _algorithm; - - /// - /// Initializes a new instance of the class. - /// - /// A collection of valid base64 encoded hashes of the certificate public key information blob. - /// The algorithm used to generate the hashes. - public CertificateSubjectPublicKeyInfoValidator([NotNull] IEnumerable validBase64EncodedSubjectPublicKeyInfoHashes, SubjectPublicKeyInfoAlgorithm algorithm) - { - _validBase64EncodedSubjectPublicKeyInfoHashes = new HashSet(validBase64EncodedSubjectPublicKeyInfoHashes); - - if (_validBase64EncodedSubjectPublicKeyInfoHashes.Count == 0) - { - throw new ArgumentOutOfRangeException(nameof(validBase64EncodedSubjectPublicKeyInfoHashes)); - } - - if (_algorithm != SubjectPublicKeyInfoAlgorithm.Sha1 && _algorithm != SubjectPublicKeyInfoAlgorithm.Sha256) - { - throw new ArgumentOutOfRangeException(nameof(algorithm)); - } - - _algorithm = algorithm; - } - - /// - /// Validates at least one SPKI hash is known. - /// - /// An object that contains state information for this validation. - /// The certificate used to authenticate the remote party. - /// The chain of certificate authorities associated with the remote certificate. - /// One or more errors associated with the remote certificate. - /// A Boolean value that determines whether the specified certificate is accepted for authentication. - public bool Validate(object sender, X509Certificate certificate, [NotNull] X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - if (sslPolicyErrors != SslPolicyErrors.None) - { - return false; - } - - if (chain.ChainElements.Count < 2) - { - return false; - } - - using (HashAlgorithm algorithm = CreateHashAlgorithm()) - { - foreach (var chainElement in chain.ChainElements) - { - X509Certificate2 chainedCertificate = chainElement.Certificate; - string base64Spki = Convert.ToBase64String(algorithm.ComputeHash(ExtractSpkiBlob(chainedCertificate))); - if (_validBase64EncodedSubjectPublicKeyInfoHashes.Contains(base64Spki)) - { - return true; - } - } - } - - return false; - } - - private static byte[] ExtractSpkiBlob(X509Certificate2 certificate) - { - // Get a native cert_context from the managed X590Certificate2 instance. - var certContext = (NativeMethods.CERT_CONTEXT)Marshal.PtrToStructure(certificate.Handle, typeof(NativeMethods.CERT_CONTEXT)); - - // Pull the CERT_INFO structure from the context. - var certInfo = (NativeMethods.CERT_INFO)Marshal.PtrToStructure(certContext.pCertInfo, typeof(NativeMethods.CERT_INFO)); - - // And finally grab the key information, public key, algorithm and parameters from it. - NativeMethods.CERT_PUBLIC_KEY_INFO publicKeyInfo = certInfo.SubjectPublicKeyInfo; - - // Now start encoding to ASN1. - // First see how large the ASN1 representation is going to be. - UInt32 blobSize = 0; - var structType = new IntPtr(NativeMethods.X509_PUBLIC_KEY_INFO); - if (!NativeMethods.CryptEncodeObject(NativeMethods.X509_ASN_ENCODING, structType, ref publicKeyInfo, null, ref blobSize)) - { - int error = Marshal.GetLastWin32Error(); - throw new Win32Exception(error); - } - - // Allocate enough space. - var blob = new byte[blobSize]; - - // Finally get the ASN1 representation. - if (!NativeMethods.CryptEncodeObject(NativeMethods.X509_ASN_ENCODING, structType, ref publicKeyInfo, blob, ref blobSize)) - { - int error = Marshal.GetLastWin32Error(); - throw new Win32Exception(error); - } - - return blob; - } - - [SuppressMessage("Microsoft.Security.Cryptography", "CA5354:SHA1CannotBeUsed", Justification = "Only used to verify cert hashes.")] - [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Caller is responsible for disposal.")] - private HashAlgorithm CreateHashAlgorithm() - { - return _algorithm == SubjectPublicKeyInfoAlgorithm.Sha1 ? (HashAlgorithm)new SHA1CryptoServiceProvider() : new SHA256CryptoServiceProvider(); - } - } -} -#endif diff --git a/src/Microsoft.AspNet.Authentication/CertificateThumbprintValidator.cs b/src/Microsoft.AspNet.Authentication/CertificateThumbprintValidator.cs deleted file mode 100644 index 6188375a1e..0000000000 --- a/src/Microsoft.AspNet.Authentication/CertificateThumbprintValidator.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#if DNX451 -using System; -using System.Collections.Generic; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Framework.Internal; - -namespace Microsoft.AspNet.Authentication -{ - /// - /// Provides pinned certificate validation based on the certificate thumbprint. - /// - public class CertificateThumbprintValidator : ICertificateValidator - { - private readonly HashSet _validCertificateThumbprints; - - /// - /// Initializes a new instance of the class. - /// - /// A set of thumbprints which are valid for an HTTPS request. - public CertificateThumbprintValidator([NotNull] IEnumerable validThumbprints) - { - _validCertificateThumbprints = new HashSet(validThumbprints, StringComparer.OrdinalIgnoreCase); - - if (_validCertificateThumbprints.Count == 0) - { - throw new ArgumentOutOfRangeException(nameof(validThumbprints)); - } - } - - /// - /// Validates that the certificate thumbprints in the signing chain match at least one whitelisted thumbprint. - /// - /// An object that contains state information for this validation. - /// The certificate used to authenticate the remote party. - /// The chain of certificate authorities associated with the remote certificate. - /// One or more errors associated with the remote certificate. - /// A Boolean value that determines whether the specified certificate is accepted for authentication. - public bool Validate(object sender, X509Certificate certificate, [NotNull] X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - if (sslPolicyErrors != SslPolicyErrors.None) - { - return false; - } - - if (chain.ChainElements.Count < 2) - { - // Self signed. - return false; - } - - foreach (var chainElement in chain.ChainElements) - { - string thumbprintToCheck = chainElement.Certificate.Thumbprint; - - if (thumbprintToCheck == null) - { - continue; - } - - if (_validCertificateThumbprints.Contains(thumbprintToCheck)) - { - return true; - } - } - - return false; - } - } -} -#endif diff --git a/src/Microsoft.AspNet.Authentication/ICertificateValidator.cs b/src/Microsoft.AspNet.Authentication/ICertificateValidator.cs deleted file mode 100644 index 4e8c2d41e0..0000000000 --- a/src/Microsoft.AspNet.Authentication/ICertificateValidator.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -#if DNX451 -using System; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; - -namespace Microsoft.AspNet.Authentication -{ - /// - /// Interface for providing pinned certificate validation, which checks HTTPS - /// communication against a known good list of certificates to protect against - /// compromised or rogue CAs issuing certificates for hosts without the - /// knowledge of the host owner. - /// - public interface ICertificateValidator - { - /// - /// Verifies the remote Secure Sockets Layer (SSL) certificate used for authentication. - /// - /// An object that contains state information for this validation. - /// The certificate used to authenticate the remote party. - /// The chain of certificate authorities associated with the remote certificate. - /// One or more errors associated with the remote certificate. - /// A Boolean value that determines whether the specified certificate is accepted for authentication. - bool Validate(Object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors); - } -} -#endif diff --git a/test/Microsoft.AspNet.Authentication.Test/CertificateSubjectKeyIdentifierValidatorTests.cs b/test/Microsoft.AspNet.Authentication.Test/CertificateSubjectKeyIdentifierValidatorTests.cs deleted file mode 100644 index a0df4a419e..0000000000 --- a/test/Microsoft.AspNet.Authentication.Test/CertificateSubjectKeyIdentifierValidatorTests.cs +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; -using Shouldly; -using Xunit; - -namespace Microsoft.AspNet.Authentication -{ - public class CertificateSubjectKeyIdentifierValidatorTests - { - private static readonly X509Certificate2 SelfSigned = new X509Certificate2("selfSigned.cer"); - private static readonly X509Certificate2 Chained = new X509Certificate2("katanatest.redmond.corp.microsoft.com.cer"); - - // The Katana test cert has a valid full chain - // katanatest.redmond.corp.microsoft.com -> MSIT Machine Auth CA2 -> Microsoft Internet Authority -> Baltimore CyberTrustRoot - - private const string KatanaTestKeyIdentifier = "d964b2941aaf3e62761041b1f3db098edfa3270a"; - private const string MicrosoftInternetAuthorityKeyIdentifier = "2a4d97955d347e9db6e633be9c27c1707e67dbc1"; - - [Fact] - public void ConstructorShouldNotThrowWithValidValues() - { - var instance = new CertificateSubjectKeyIdentifierValidator(new[] { string.Empty }); - - instance.ShouldNotBe(null); - } - - [Fact] - public void ConstructorShouldThrownWhenTheValidHashEnumerableIsNull() - { - Should.Throw(() => - new CertificateSubjectKeyIdentifierValidator(null)); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenSslPolicyErrorsIsRemoteCertificateChainErrors() - { - var instance = new CertificateSubjectKeyIdentifierValidator(new[] { string.Empty }); - bool result = instance.Validate(null, null, null, SslPolicyErrors.RemoteCertificateChainErrors); - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenSslPolicyErrorsIsRemoteCertificateNameMismatch() - { - var instance = new CertificateSubjectKeyIdentifierValidator(new[] { string.Empty }); - bool result = instance.Validate(null, null, null, SslPolicyErrors.RemoteCertificateNameMismatch); - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenSslPolicyErrorsIsRemoteCertificateNotAvailable() - { - var instance = new CertificateSubjectKeyIdentifierValidator(new[] { string.Empty }); - bool result = instance.Validate(null, null, null, SslPolicyErrors.RemoteCertificateNotAvailable); - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenPassedASelfSignedCertificate() - { - var instance = new CertificateSubjectKeyIdentifierValidator(new[] { string.Empty }); - var certificateChain = new X509Chain(); - certificateChain.Build(SelfSigned); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, SelfSigned, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenPassedATrustedCertificateWhichDoesNotHaveAWhitelistedSubjectKeyIdentifier() - { - var instance = new CertificateSubjectKeyIdentifierValidator(new[] { string.Empty }); - var certificateChain = new X509Chain(); - certificateChain.Build(Chained); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, Chained, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnTrueWhenPassedATrustedCertificateWhichHasItsSubjectKeyIdentifierWhiteListed() - { - var instance = new CertificateSubjectKeyIdentifierValidator( - new[] - { - KatanaTestKeyIdentifier - }); - - var certificateChain = new X509Chain(); - certificateChain.Build(Chained); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, Chained, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(true); - } - - [Fact] - public void ValidatorShouldReturnTrueWhenPassedATrustedCertificateWhichHasAChainElementSubjectKeyIdentifierWhiteListed() - { - var instance = new CertificateSubjectKeyIdentifierValidator( - new[] - { - MicrosoftInternetAuthorityKeyIdentifier - }); - var certificateChain = new X509Chain(); - certificateChain.Build(Chained); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, Chained, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(true); - } - } -} diff --git a/test/Microsoft.AspNet.Authentication.Test/CertificateSubjectPublicKeyInfoValidatorTests.cs b/test/Microsoft.AspNet.Authentication.Test/CertificateSubjectPublicKeyInfoValidatorTests.cs deleted file mode 100644 index 366e2f3b56..0000000000 --- a/test/Microsoft.AspNet.Authentication.Test/CertificateSubjectPublicKeyInfoValidatorTests.cs +++ /dev/null @@ -1,173 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; -using Shouldly; -using Xunit; - -namespace Microsoft.AspNet.Authentication -{ - public class CertificateSubjectPublicKeyInfoValidatorTests - { - private static readonly X509Certificate2 SelfSigned = new X509Certificate2("selfSigned.cer"); - private static readonly X509Certificate2 Chained = new X509Certificate2("katanatest.redmond.corp.microsoft.com.cer"); - - // The Katana test cert has a valid full chain - // katanatest.redmond.corp.microsoft.com -> MSIT Machine Auth CA2 -> Microsoft Internet Authority -> Baltimore CyberTrustRoot - - // The following fingerprints were generated using the go program in appendix A of the Public Key Pinning Extension for HTTP - // draft-ietf-websec-key-pinning-05 - - private const string KatanaTestSha1Hash = "xvNsCWwxvL3qsCYChZLiwNm1D6o="; - private const string KatanaTestSha256Hash = "AhR1Y/xhxK2uD7YJ0xKUPq8tYrWm4+F7DgO2wUOqB+4="; - - private const string MicrosoftInternetAuthoritySha1Hash = "Z3HnseSVDEPu5hZoj05/bBSnT/s="; - private const string MicrosoftInternetAuthoritySha256Hash = "UQTPeq/Tlg/vLt2ijtl7qlMFBFkbGG9aAWJbQMOMWFg="; - - [Fact] - public void ConstructorShouldNotThrowWithValidValues() - { - var instance = new CertificateSubjectPublicKeyInfoValidator(new string[1], SubjectPublicKeyInfoAlgorithm.Sha1); - - instance.ShouldNotBe(null); - } - - [Fact] - public void ConstructorShouldThrownWhenTheValidHashEnumerableIsNull() - { - Should.Throw(() => - new CertificateSubjectPublicKeyInfoValidator(null, SubjectPublicKeyInfoAlgorithm.Sha1)); - } - - [Fact] - public void ConstructorShouldThrowWhenTheHashEnumerableContainsNoHashes() - { - Should.Throw(() => - new CertificateSubjectPublicKeyInfoValidator(new string[0], SubjectPublicKeyInfoAlgorithm.Sha1)); - } - - [Fact] - public void ConstructorShouldThrowIfAnInvalidAlgorithmIsPassed() - { - Should.Throw(() => - new CertificateSubjectPublicKeyInfoValidator(new string[0], (SubjectPublicKeyInfoAlgorithm)2)); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenSslPolicyErrorsIsRemoteCertificateChainErrors() - { - var instance = new CertificateSubjectPublicKeyInfoValidator(new string[1], SubjectPublicKeyInfoAlgorithm.Sha1); - bool result = instance.Validate(null, null, null, SslPolicyErrors.RemoteCertificateChainErrors); - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenSslPolicyErrorsIsRemoteCertificateNameMismatch() - { - var instance = new CertificateSubjectPublicKeyInfoValidator(new string[1], SubjectPublicKeyInfoAlgorithm.Sha1); - bool result = instance.Validate(null, null, null, SslPolicyErrors.RemoteCertificateNameMismatch); - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenSslPolicyErrorsIsRemoteCertificateNotAvailable() - { - var instance = new CertificateSubjectPublicKeyInfoValidator(new string[1], SubjectPublicKeyInfoAlgorithm.Sha1); - bool result = instance.Validate(null, null, null, SslPolicyErrors.RemoteCertificateNotAvailable); - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenPassedASelfSignedCertificate() - { - var instance = new CertificateSubjectPublicKeyInfoValidator(new string[1], SubjectPublicKeyInfoAlgorithm.Sha1); - var certificateChain = new X509Chain(); - certificateChain.Build(SelfSigned); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, SelfSigned, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenPassedATrustedCertificateWhichDoesNotHaveAWhitelistedSha1Spki() - { - var instance = new CertificateSubjectPublicKeyInfoValidator(new string[1], SubjectPublicKeyInfoAlgorithm.Sha1); - var certificateChain = new X509Chain(); - certificateChain.Build(Chained); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, Chained, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnTrueWhenPassedATrustedCertificateWhichHasItsSha1SpkiWhiteListed() - { - var instance = new CertificateSubjectPublicKeyInfoValidator(new[] { KatanaTestSha1Hash }, SubjectPublicKeyInfoAlgorithm.Sha1); - var certificateChain = new X509Chain(); - certificateChain.Build(Chained); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, Chained, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(true); - } - - [Fact] - public void ValidatorShouldReturnTrueWhenPassedATrustedCertificateWhichHasAChainElementSha1SpkiWhiteListed() - { - var instance = new CertificateSubjectPublicKeyInfoValidator(new[] { MicrosoftInternetAuthoritySha1Hash }, SubjectPublicKeyInfoAlgorithm.Sha1); - var certificateChain = new X509Chain(); - certificateChain.Build(Chained); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, Chained, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(true); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenPassedATrustedCertificateWhichDoesNotHaveAWhitelistedSha256Spki() - { - var instance = new CertificateSubjectPublicKeyInfoValidator(new string[1], SubjectPublicKeyInfoAlgorithm.Sha256); - var certificateChain = new X509Chain(); - certificateChain.Build(Chained); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, Chained, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnTrueWhenPassedATrustedCertificateWhichHasItsSha256SpkiWhiteListed() - { - var instance = new CertificateSubjectPublicKeyInfoValidator(new[] { KatanaTestSha256Hash }, SubjectPublicKeyInfoAlgorithm.Sha256); - var certificateChain = new X509Chain(); - certificateChain.Build(Chained); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, Chained, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(true); - } - - [Fact] - public void ValidatorShouldReturnTrueWhenPassedATrustedCertificateWhichHasAChainElementSha256SpkiWhiteListed() - { - var instance = new CertificateSubjectPublicKeyInfoValidator(new[] { MicrosoftInternetAuthoritySha256Hash }, SubjectPublicKeyInfoAlgorithm.Sha256); - var certificateChain = new X509Chain(); - certificateChain.Build(Chained); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, Chained, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(true); - } - } -} diff --git a/test/Microsoft.AspNet.Authentication.Test/CertificateThumbprintValidatorTests.cs b/test/Microsoft.AspNet.Authentication.Test/CertificateThumbprintValidatorTests.cs deleted file mode 100644 index 30537c51de..0000000000 --- a/test/Microsoft.AspNet.Authentication.Test/CertificateThumbprintValidatorTests.cs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System; -using System.Net.Security; -using System.Security.Cryptography.X509Certificates; -using Shouldly; -using Xunit; - -namespace Microsoft.AspNet.Authentication -{ - public class CertificateThumbprintValidatorTests - { - private static readonly X509Certificate2 SelfSigned = new X509Certificate2("selfSigned.cer"); - private static readonly X509Certificate2 Chained = new X509Certificate2("katanatest.redmond.corp.microsoft.com.cer"); - - // The Katana test cert has a valid full chain - // katanatest.redmond.corp.microsoft.com -> MSIT Machine Auth CA2 -> Microsoft Internet Authority -> Baltimore CyberTrustRoot - - private const string KatanaTestThumbprint = "a9894c464b260cac3f5b91cece33b3c55e82e61c"; - private const string MicrosoftInternetAuthorityThumbprint = "992ad44d7dce298de17e6f2f56a7b9caa41db93f"; - - [Fact] - public void ConstructorShouldNotThrowWithValidValues() - { - var instance = new CertificateThumbprintValidator(new string[1]); - - instance.ShouldNotBe(null); - } - - [Fact] - public void ConstructorShouldThrownWhenTheValidHashEnumerableIsNull() - { - Should.Throw(() => - new CertificateThumbprintValidator(null)); - } - - [Fact] - public void ConstructorShouldThrowWhenTheHashEnumerableContainsNoHashes() - { - Should.Throw(() => - new CertificateThumbprintValidator(new string[0])); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenSslPolicyErrorsIsRemoteCertificateChainErrors() - { - var instance = new CertificateThumbprintValidator(new string[1]); - bool result = instance.Validate(null, null, null, SslPolicyErrors.RemoteCertificateChainErrors); - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenSslPolicyErrorsIsRemoteCertificateNameMismatch() - { - var instance = new CertificateThumbprintValidator(new string[1]); - bool result = instance.Validate(null, null, null, SslPolicyErrors.RemoteCertificateNameMismatch); - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenSslPolicyErrorsIsRemoteCertificateNotAvailable() - { - var instance = new CertificateThumbprintValidator(new string[1]); - bool result = instance.Validate(null, null, null, SslPolicyErrors.RemoteCertificateNotAvailable); - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenPassedASelfSignedCertificate() - { - var instance = new CertificateThumbprintValidator(new string[1]); - var certificateChain = new X509Chain(); - certificateChain.Build(SelfSigned); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, SelfSigned, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnFalseWhenPassedATrustedCertificateWhichDoesNotHaveAWhitelistedThumbprint() - { - var instance = new CertificateThumbprintValidator(new string[1]); - var certificateChain = new X509Chain(); - certificateChain.Build(Chained); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, Chained, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(false); - } - - [Fact] - public void ValidatorShouldReturnTrueWhenPassedATrustedCertificateWhichHasItsThumbprintWhiteListed() - { - var instance = new CertificateThumbprintValidator(new[] { KatanaTestThumbprint }); - var certificateChain = new X509Chain(); - certificateChain.Build(Chained); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, Chained, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(true); - } - - [Fact] - public void ValidatorShouldReturnTrueWhenPassedATrustedCertificateWhichHasAChainElementThumbprintWhiteListed() - { - var instance = new CertificateThumbprintValidator(new[] { MicrosoftInternetAuthorityThumbprint }); - var certificateChain = new X509Chain(); - certificateChain.Build(Chained); - certificateChain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - - bool result = instance.Validate(null, Chained, certificateChain, SslPolicyErrors.None); - - result.ShouldBe(true); - } - } -} diff --git a/test/Microsoft.AspNet.Authentication.Test/Twitter/TwitterMiddlewareTests.cs b/test/Microsoft.AspNet.Authentication.Test/Twitter/TwitterMiddlewareTests.cs index d837cdaffc..33531ba058 100644 --- a/test/Microsoft.AspNet.Authentication.Test/Twitter/TwitterMiddlewareTests.cs +++ b/test/Microsoft.AspNet.Authentication.Test/Twitter/TwitterMiddlewareTests.cs @@ -48,7 +48,6 @@ namespace Microsoft.AspNet.Authentication.Twitter return null; } }; - options.BackchannelCertificateValidator = null; }, context => { @@ -123,7 +122,6 @@ namespace Microsoft.AspNet.Authentication.Twitter return null; } }; - options.BackchannelCertificateValidator = null; }, context => {