private async Task <bool> ValidateRequest(HttpRequest request, SkillRequest skillRequest)
        {
            try
            {
                request.Headers.TryGetValue("SignatureCertChainUrl", out var signatureChainUrl);
                if (string.IsNullOrWhiteSpace(signatureChainUrl))
                {
                    return(false);
                }

                Uri certUrl;
                try
                {
                    certUrl = new Uri(signatureChainUrl);
                }
                catch
                {
                    return(false);
                }

                request.Headers.TryGetValue("Signature", out var signature);
                if (string.IsNullOrWhiteSpace(signature))
                {
                    return(false);
                }
                var body = "";
                request.EnableRewind();
                using (var stream = new StreamReader(request.Body))
                {
                    stream.BaseStream.Position = 0;
                    body = stream.ReadToEnd();
                    stream.BaseStream.Position = 0;
                }

                if (string.IsNullOrWhiteSpace(body))
                {
                    return(false);
                }

                bool isTimestampValid = RequestVerification.RequestTimestampWithinTolerance(skillRequest);
                bool valid            = await RequestVerification.Verify(signature, certUrl, body);

                if (!valid || !isTimestampValid)
                {
                    return(false);
                }
                else
                {
                    return(true);
                }
            }
            catch
            {
                return(false);
            }
        }
Exemple #2
0
        private static async Task <bool> ValidateRequest(HttpRequest request, ILogger log, SkillRequest skillRequest)
        {
            request.Headers.TryGetValue("SignatureCertChainUrl", out var signatureChainUrl);
            if (string.IsNullOrWhiteSpace(signatureChainUrl))
            {
                log.LogError("Validation failed. Empty SignatureCertChainUrl header");
                return(false);
            }

            Uri certUrl;

            try
            {
                certUrl = new Uri(signatureChainUrl);
            }
            catch
            {
                log.LogError($"Validation failed. SignatureChainUrl not valid: {signatureChainUrl}");
                return(false);
            }

            request.Headers.TryGetValue("Signature", out var signature);
            if (string.IsNullOrWhiteSpace(signature))
            {
                log.LogError("Validation failed - Empty Signature header");
                return(false);
            }

            request.Body.Position = 0;
            var body = await request.ReadAsStringAsync();

            request.Body.Position = 0;

            if (string.IsNullOrWhiteSpace(body))
            {
                log.LogError("Validation failed - the JSON is empty");
                return(false);
            }

            bool isTimestampValid = RequestVerification.RequestTimestampWithinTolerance(skillRequest);
            bool valid            = await RequestVerification.Verify(signature, certUrl, body, GetCertificate);

            // bool valid = await RequestVerification.Verify(signature, certUrl, body);

            if (!valid || !isTimestampValid)
            {
                log.LogError("Validation failed - RequestVerification failed");
                return(false);
            }
            else
            {
                return(true);
            }
        }
Exemple #3
0
        public void Replay_Attack_Timestamp_Invalidated_By_RequestVerification()
        {
            var request = new SkillRequest
            {
                Request = new LaunchRequest {
                    Timestamp = DateTime.Now.AddMinutes(3)
                }
            };

            Assert.False(RequestVerification.RequestTimestampWithinTolerance(request));
        }
Exemple #4
0
        public void New_Request_Timestamp_validated_By_RequestVerification()
        {
            var request = new SkillRequest
            {
                Request = new LaunchRequest {
                    Timestamp = DateTime.Now.AddMinutes(1)
                }
            };

            Assert.True(RequestVerification.RequestTimestampWithinTolerance(request));
        }
        public static async Task <bool> ValidateRequestAsync(this SkillRequest skillRequest, HttpRequest request, ILogger log)
        {
            // Verifies that the request is indeed coming from Alexa.

            request.Headers.TryGetValue("SignatureCertChainUrl", out var signatureChainUrl);
            if (string.IsNullOrWhiteSpace(signatureChainUrl))
            {
                log.LogError("Validation failed. Empty SignatureCertChainUrl header");
                return(false);
            }

            Uri certUrl;

            try
            {
                certUrl = new Uri(signatureChainUrl);
            }
            catch
            {
                log.LogError($"Validation failed. SignatureChainUrl not valid: {signatureChainUrl}");
                return(false);
            }

            request.Headers.TryGetValue("Signature", out var signature);
            if (string.IsNullOrWhiteSpace(signature))
            {
                log.LogError("Validation failed - Empty Signature header");
                return(false);
            }

            request.Body.Position = 0;
            var body = request.Body.ToString();

            request.Body.Position = 0;

            if (string.IsNullOrWhiteSpace(body))
            {
                log.LogError("Validation failed - the JSON is empty");
                return(false);
            }

            var isTimestampValid = RequestVerification.RequestTimestampWithinTolerance(skillRequest);
            var isValid          = await RequestVerification.Verify(signature, certUrl, body);

            if (!isValid || !isTimestampValid)
            {
                log.LogError("Validation failed - RequestVerification failed");
                return(false);
            }

            return(true);
        }
Exemple #6
0
        private async Task <bool> ValidateRequest(HttpRequest request, SkillRequest skillRequest)
        {
            try {
                var header    = request.Headers;
                var signature = header["Signature"];
                var certUrl   = new Uri(header["SignatureCertChainUrl"]);
                var body      = await request.ReadAsStringAsync();

                return
                    (RequestVerification.RequestTimestampWithinTolerance(skillRequest) &&
                     await RequestVerification.Verify(signature, certUrl, body));
            } catch {
                m_logger.LogError("Validation exception");
                return(false);
            }
        }
Exemple #7
0
        private static async Task <bool> ValidateRequestAsync(HttpRequest request, SkillRequest skillRequest)
        {
            request.Headers.TryGetValue("SignatureCertChainUrl", out var signatureChainUrl);
            if (string.IsNullOrWhiteSpace(signatureChainUrl))
            {
                return(false);
            }

            Uri certUrl;

            try
            {
                certUrl = new Uri(signatureChainUrl);
            }
            catch
            {
                return(false);
            }

            request.Headers.TryGetValue("Signature", out var signature);
            if (string.IsNullOrWhiteSpace(signature))
            {
                return(false);
            }

            request.Body.Position = 0;
            var body = await request.ReadAsStringAsync();

            request.Body.Position = 0;

            if (string.IsNullOrWhiteSpace(body))
            {
                return(false);
            }

            bool isTimestampValid = RequestVerification.RequestTimestampWithinTolerance(skillRequest);
            bool valid            = await RequestVerification.Verify(signature, certUrl, body);

            if (!valid || !isTimestampValid)
            {
                return(false);
            }
            else
            {
                return(true);
            }
        }
        /// <summary>
        /// Authorize the SkillRequest is coming from Alexa.
        /// </summary>
        /// <param name="skillRequest">Incoming SkillRequest from Alexa.</param>
        /// <param name="requestBody">Full request body from Alexa.</param>
        /// <param name="signatureChainUrl">Signature Chain Url. This is the SignatureCertChainUrl header value.</param>
        /// <param name="signature">Signature. This is the Signature header value.</param>
        /// <returns>True if this is a valid SkillRequest otherwise false.</returns>
        public virtual async Task <bool> ValidateSkillRequest(CrunchRequest skillRequest, string requestBody, string signatureChainUrl, string signature)
        {
            if (skillRequest == null)
            {
                _logger.LogError("Validation failed. No incoming skill request.");
                return(false);
            }

            if (string.IsNullOrWhiteSpace(signatureChainUrl))
            {
                _logger.LogError("Validation failed. Empty SignatureCertChainUrl header.");
                return(false);
            }

            Uri certUrl;

            try
            {
                certUrl = new Uri(signatureChainUrl);
            }
            catch
            {
                _logger.LogError($"Validation failed. SignatureChainUrl not valid: {signatureChainUrl}.");
                return(false);
            }

            if (string.IsNullOrWhiteSpace(signature))
            {
                _logger.LogError("Validation failed. Empty Signature header.");
                return(false);
            }

            if (!RequestVerification.RequestTimestampWithinTolerance(skillRequest))
            {
                _logger.LogError("Validation failed. Request timestamp outside of tolerance.");
                return(false);
            }
            if (!await RequestVerification.Verify(signature, certUrl, requestBody))
            {
                _logger.LogError("Validation failed. Alexa certificate validation failed.");
                return(false);
            }

            return(true);
        }
Exemple #9
0
        protected async Task <ActionResult> CheckBadRequest(SkillRequest skillRequest)
        {
            try
            {
                if (!RequestVerification.RequestTimestampWithinTolerance(skillRequest))
                {
                    LogMessage("Request failed due to TimestampTolerance", SeverityLevel.Error, null);
                    return(BadRequest());
                }

                var sigCertChainUrl = Request.Headers["SignatureCertChainUrl"];
                if (String.IsNullOrWhiteSpace(sigCertChainUrl))
                {
                    LogMessage("Request failed due to no SignatureCertChainUrl", SeverityLevel.Error, null);
                    return(BadRequest());
                }

                var signature = Request.Headers["Signature"];
                if (String.IsNullOrWhiteSpace(signature))
                {
                    LogMessage("Request failed due to no Signature", SeverityLevel.Error, null);
                    return(BadRequest());
                }

                var sigCertChainPath = new Uri(sigCertChainUrl);
                if (!RequestVerification.VerifyCertificateUrl(sigCertChainPath))
                {
                    LogMessage($"Request failed due to an invalid Certificate Url ({sigCertChainPath})", SeverityLevel.Error, null);
                    return(BadRequest());
                }

                //var cert = await RequestVerification.GetCertificate(sigCertChainPath);
                //if (!RequestVerification.VerifyChain(cert))
                //{
                //    LogMessage("Request failed due to invalid Certificate Chain", SeverityLevel.Error, null);
                //    return BadRequest();
                //}

                //Request.Body.Position = 0;
                var body = await new StreamReader(Request.Body, Encoding.UTF8).ReadToEndAsync();
                //Request.Body.Position = 0;

                if (!await RequestVerification.Verify(signature, sigCertChainPath, body))
                {
                    LogMessage($"Request verification failed! (sig: {signature}, sig cert chain: {sigCertChainPath}, request details: {await GetRequestDetails()})", SeverityLevel.Error, null);
                    return(BadRequest());
                }
            }
            catch (Exception exc)
            {
                LogMessage($"Request failed because of unknown error. Request: {await GetRequestDetails()}", SeverityLevel.Error, new Dictionary <string, string>()
                {
                    { "StackTrace", exc.StackTrace }
                });
                return(BadRequest());
            }

            //Success, let's log the request info temporarily
            LogMessage($"Successful request: {await GetRequestDetails()}", SeverityLevel.Verbose, "AlexaBaseController", "CheckBadRequest");
            return(null);
        }
 /// <summary>
 /// Validates the timestamp.
 /// </summary>
 /// <param name="skillRequest">The current skill request.</param>
 private static bool IsTimestampValid(SkillRequest skillRequest)
 {
     return(RequestVerification.RequestTimestampWithinTolerance(skillRequest));
 }
Exemple #11
0
        public IActionResult HandleSkillRequest()
        {
            string body;

            using (var reader = new StreamReader(Request.Body, Encoding.UTF8))
            {
                body = reader.ReadToEnd();
                m_Logger.LogDebug("body: " + body);
            }

            SkillRequest input = JsonConvert.DeserializeObject <SkillRequest>(body);

            string signatureCertChainUrl = Request.Headers["SignatureCertChainUrl"];
            string signature             = Request.Headers["Signature"];

            m_Logger.LogDebug("signatureCertChainUrl: " + signatureCertChainUrl);
            m_Logger.LogDebug("signature: " + signature);

            if (string.IsNullOrEmpty(signatureCertChainUrl) || string.IsNullOrEmpty(signature))
            {
                return(BadRequest());
            }

            m_Logger.LogDebug("HandleSkillRequest: " + input.Session.Application.ApplicationId);

            if (input.Session.Application.ApplicationId != _appid)
            {
                m_Logger.LogDebug("ApplicationId wrong");
                return(BadRequest());
            }

            if (!RequestVerification.VerifyCertificateUrl(new Uri(signatureCertChainUrl)))
            {
                m_Logger.LogDebug("VerifyCertificateUrl: false");
                return(BadRequest());
            }

            var certificate = RequestVerification.GetCertificate(new Uri(signatureCertChainUrl)).Result;

            if (!RequestVerification.VerifyChain(certificate))
            {
                m_Logger.LogDebug("VerifyChain: false");
                return(BadRequest());
            }

            if (!RequestVerification.AssertHashMatch(certificate, signature, body))
            {
                m_Logger.LogDebug("AssertHashMatch: false");
                return(BadRequest());
            }

            if (!RequestVerification.RequestTimestampWithinTolerance(input))
            {
                m_Logger.LogDebug("RequestTimestampWithinTolerance: false");
                return(BadRequest());
            }

            var requestType = input.GetRequestType();

            if (requestType == typeof(IntentRequest))
            {
                m_Logger.LogInformation("requestType IntentRequest");
                var response = HandleIntents(input);
                return(Ok(response));
            }

            if (requestType == typeof(LaunchRequest))
            {
                m_Logger.LogInformation("requestType LaunchRequest");
                return(Ok(BuildResponse(Statics.WelcomeMessage, false)));
            }

            m_Logger.LogWarning("ErrorResponse");
            return(Ok(BuildResponse(Statics.ErrorMessage, true)));
        }