/// <summary>
        /// Checks if a request is valid based on what the client passed
        /// </summary>
        /// <param name="content">The content that the client passed</param>
        /// <param name="resource">The resource that the client requested (URI ENCODED)</param>
        /// <param name="resourceRequestMethod">The method that the client used to request the resource (ALL UPPER)</param>
        /// <param name="appId">The appId the client is claiming to be</param>
        /// <param name="incomingBase64Signature">The base64 signature the client passed</param>
        /// <param name="nonce">The nonce the client provided to identify the request</param>
        /// <param name="requestTimeStamp">The timestamp the client provided to identify the request</param>
        /// <returns>(Is the request valid, description of the result)</returns>
        protected virtual Tuple <bool, HmacIsValidRequestResult> IsValidRequest(Stream content, string resource, string resourceRequestMethod, string appId,
                                                                                string incomingBase64Signature, string nonce, string requestTimeStamp)
        {
            if (string.IsNullOrWhiteSpace(resource))
            {
                LoggingService.LogMessage("HMAC Auth Resource Not Valid",
                                          "No valid request requested resource", LogLevel.Debug);
                return(new Tuple <bool, HmacIsValidRequestResult>(false, HmacIsValidRequestResult.NoValidResouce));
            }

            string requestContentBase64String = "";

            ApiKeyService.TryGetValue(appId, out string sharedKey);
            if (string.IsNullOrWhiteSpace(sharedKey))
            {
                LoggingService.LogMessage("Api Auth Request Not Valid",
                                          "Unable to find appId", LogLevel.Debug);
                return(new Tuple <bool, HmacIsValidRequestResult>(false, HmacIsValidRequestResult.UnableToFindAppId));
            }

            if (IsReplayRequest(nonce, requestTimeStamp))
            {
                LoggingService.LogMessage("Api Auth Request Not Valid",
                                          "Looked like a replay request.\r\nNonce - " + nonce + "\r\nRequest Timestamp - " + requestTimeStamp
                                          + "\r\nOur Timestamp" + (DateTime.UtcNow - Constants.DateTime.UnixEpoch).TotalSeconds, LogLevel.Debug);
                return(new Tuple <bool, HmacIsValidRequestResult>(false,
                                                                  HmacIsValidRequestResult.ReplayRequest));
            }

            // we need a content stream (we need to make sure we pass this back)
            Tuple <Stream, byte[], string> hashAndContent = ComputeHash(content);

            if (hashAndContent.Item2 != null)
            {
                requestContentBase64String = Convert.ToBase64String(hashAndContent.Item2);
            }

            string encodedResource =
                System.Web.HttpUtility.UrlEncode(resource.ToLower());
            string data =
                $"{appId}{resourceRequestMethod}{encodedResource}{requestTimeStamp}{nonce}{requestContentBase64String}";

            byte[] secretKeyBytes = Convert.FromBase64String(sharedKey);

            byte[] signature = data.GetBytes();

            using (HMACSHA256 hmac = new HMACSHA256(secretKeyBytes))
            {
                byte[] signatureBytes = hmac.ComputeHash(signature);

                string signatureString = Convert.ToBase64String(signatureBytes);
                bool   matched         = incomingBase64Signature.Equals(signatureString,
                                                                        StringComparison.Ordinal);
                if (!matched)
                {
                    LoggingService.LogMessage("Api Auth Request Not Valid",
                                              "Signatures didn't match.\r\nRequest Signature - " + incomingBase64Signature
                                              + ".\r\nInternal Signature - " + signatureString + ".\r\nInternal signature data - " + data
                                              + "\r\nRaw Content - " + hashAndContent.Item2,
                                              LogLevel.Debug);
                }
                return(new Tuple <bool, HmacIsValidRequestResult>(matched, matched
                                        ? HmacIsValidRequestResult.NoError
                                        : HmacIsValidRequestResult.SignaturesMismatch));
            }
        }