Esempio n. 1
0
        public void ShouldCreateSignature()
        {
            // Arrange
            IHmacConfiguration configuration = CreateConfiguration();
            HmacSigner         signer        = new HmacSigner(configuration, _keyRepository);
            HmacSignatureData  signatureData = new HmacSignatureData
            {
                Key         = _keyRepository.Key,
                HttpMethod  = "POST",
                ContentMd5  = _base64Md5Hash,
                ContentType = ContentType,
                Date        = "Wed, 30 Dec 2015 12:30:45 GMT",
                Username    = _keyRepository.Username,
                RequestUri  = Url,
                Headers     = new NameValueCollection {
                    { "X-Custom-Test-Header-1", "Test1" }, { "X-Custom-Test-Header-2", "Test2" }
                }
            };
            const string expectedSignature = "CSDWHwt5sOWkBKS5mSNWrgJaXREQB6CKywVyB/A4IDQ65h3gzR9/Uutug34ikpcW3JlnVyAL+xbu/eNaq99q/Q==";

            HmacSignatureData signatureData2 = new HmacSignatureData {
                Key = _keyRepository.Key
            };
            const string expectedSignature2 = "QwPLzI1RUBRyYerrolY3+4Mzuw8Z07YfxnpP9va2ckH/I7UvdPBMkcaomWOaC5pZym9x+t/BA/2VTP6pjje1DQ==";

            // Act
            string signature  = signer.CreateSignature(signatureData);
            string signature2 = signer.CreateSignature(signatureData2);

            // Assert
            Assert.IsNotNull(signature);
            Assert.AreEqual(expectedSignature, signature);
            Assert.IsNotNull(signature2);
            Assert.AreEqual(expectedSignature2, signature2);
        }
Esempio n. 2
0
        public void ShouldFailValidationDueToMissingDate()
        {
            // Arrange
            IHmacConfiguration configuration  = CreateConfiguration();
            IHmacSigner        signer         = new HmacSigner(configuration, _keyRepository);
            HmacValidator      validator      = new HmacValidator(configuration, signer);
            DateTimeOffset     dateTimeOffset = DateTimeOffset.UtcNow.AddMinutes(-3);
            string             dateString     = dateTimeOffset.ToString(HmacConstants.DateHeaderFormat, _dateHeaderCulture);
            HttpRequestBase    request        = CreateRequest(dateString);
            HmacSignatureData  signatureData  = signer.GetSignatureDataFromHttpRequest(request);
            string             signature      = signer.CreateSignature(signatureData);

            request.Headers[HmacConstants.AuthorizationHeaderName] = string.Format(
                HmacConstants.AuthorizationHeaderFormat,
                configuration.AuthorizationScheme,
                signature);

            request.Headers.Remove(HmacConstants.DateHeaderName);

            // Act
            HmacValidationResult result = validator.ValidateHttpRequest(request);

            // Assert
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.ErrorMessage);
            Assert.AreEqual(result.ResultCode, HmacValidationResultCode.DateMissing);
        }
Esempio n. 3
0
        public void ShouldFailValidationDueToMissingKey()
        {
            // Arrange
            Mock <IHmacKeyRepository> mockKeyRepo = new Mock <IHmacKeyRepository>();

            mockKeyRepo.Setup(r => r.GetHmacKeyForUsername(It.IsAny <string>())).Returns((string)null);
            IHmacConfiguration configuration  = CreateConfiguration();
            IHmacSigner        signer         = new HmacSigner(configuration, mockKeyRepo.Object);
            HmacValidator      validator      = new HmacValidator(configuration, signer);
            DateTimeOffset     dateTimeOffset = DateTimeOffset.UtcNow.AddMinutes(-3);
            string             dateString     = dateTimeOffset.ToString(HmacConstants.DateHeaderFormat, _dateHeaderCulture);
            HttpRequestBase    request        = CreateRequest(dateString);
            HmacSignatureData  signatureData  = signer.GetSignatureDataFromHttpRequest(request);

            signatureData.Key = "TestKey";
            string signature = signer.CreateSignature(signatureData);

            request.Headers[HmacConstants.AuthorizationHeaderName] = string.Format(
                HmacConstants.AuthorizationHeaderFormat,
                configuration.AuthorizationScheme,
                signature);

            // Act
            HmacValidationResult result = validator.ValidateHttpRequest(request);

            // Assert
            Assert.IsNotNull(result);
            Assert.IsNotNull(result.ErrorMessage);
            Assert.AreEqual(result.ResultCode, HmacValidationResultCode.KeyMissing);
        }
Esempio n. 4
0
        private HmacValidationResult ValidateHttpRequest(HmacRequestWrapper request, HmacSignatureData signatureData)
        {
            if (string.IsNullOrEmpty(HmacConfiguration.AuthorizationScheme))
            {
                throw new HmacConfigurationException("The AuthorizationScheme cannot be null or empty.");
            }

            // Note: the Content-MD5 and Content-Type headers are only required if the request contains a body

            // If configured, the request date is validated to prevent replay attacks
            if (HmacConfiguration.MaxRequestAge.HasValue)
            {
                if (!request.Date.HasValue)
                {
                    return(new HmacValidationResult(HmacValidationResultCode.DateMissing, "The request date was not found."));
                }
                if (!IsValidRequestDate(request.Date.Value))
                {
                    return(new HmacValidationResult(HmacValidationResultCode.DateInvalid, "The request date is invalid."));
                }
            }

            // The username is always required when the header has been configured
            if (!string.IsNullOrEmpty(HmacConfiguration.UserHeaderName) && string.IsNullOrEmpty(signatureData.Username))
            {
                return(new HmacValidationResult(HmacValidationResultCode.UsernameMissing, "The username is required but was not found."));
            }

            // The key must be found
            if (string.IsNullOrEmpty(signatureData.Key))
            {
                return(new HmacValidationResult(HmacValidationResultCode.KeyMissing, "The key was not found."));
            }

            // If configured, an MD5 hash of the body is generated and compared with the Content-MD5 header value to check if the body hasn't been altered
            if (HmacConfiguration.ValidateContentMd5 && !IsValidContentMd5(signatureData.ContentMd5, request.Content))
            {
                if (string.IsNullOrEmpty(signatureData.ContentMd5))
                {
                    return(new HmacValidationResult(HmacValidationResultCode.BodyHashMissing, "The MD5 body hash was not found."));
                }
                return(new HmacValidationResult(HmacValidationResultCode.BodyHashMismatch, "The body content differs."));
            }

            // The Authorization header is always required and should contain the scheme and signature

            IList <string> authorizations = request.Headers.GetValues(HmacConstants.AuthorizationHeaderName);
            string         authorization;

            if (authorizations == null || string.IsNullOrEmpty(authorization = authorizations.FirstOrDefault()))
            {
                return(new HmacValidationResult(HmacValidationResultCode.AuthorizationMissing, "The signature was not found."));
            }

            string[] authorizationParts = authorization.Split(' ');

            if (authorizationParts.Length < 2 || authorizationParts[0] != HmacConfiguration.AuthorizationScheme)
            {
                return(new HmacValidationResult(HmacValidationResultCode.AuthorizationInvalid, "The signature was not correctly specified."));
            }

            // Finally, the signature from the Authorization header should match the newly created signature

            string signature = authorizationParts[1];

            string newSignature = HmacSigner.CreateSignature(signatureData);

            if (!IsValidSignature(signature, newSignature))
            {
                return(new HmacValidationResult(HmacValidationResultCode.SignatureMismatch, "The signature does not match."));
            }

            return(HmacValidationResult.Ok);
        }