public void VerifyCertificateUrlTest()
        {
            // samples from
            // https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-web-service

            var validUrls = new string[] {
                "https://s3.amazonaws.com/echo.api/echo-api-cert.pem",
                "https://s3.amazonaws.com:443/echo.api/echo-api-cert.pem",
                "https://s3.amazonaws.com/echo.api/../echo.api/echo-api-cert.pem"
            };

            var invalidUrls = new string[] {
                "http://s3.amazonaws.com/echo.api/echo-api-cert.pem",
                "https://notamazon.com/echo.api/echo-api-cert.pem",
                "https://s3.amazonaws.com/EcHo.aPi/echo-api-cert.pem",
                "https://s3.amazonaws.com/invalid.path/echo-api-cert.pem",
                "https://s3.amazonaws.com:563/echo.api/echo-api-cert.pem"
            };

            foreach (var validUrl in validUrls)
            {
                Assert.True(SpeechletRequestSignatureVerifier.VerifyCertificateUrl(validUrl));
            }

            foreach (var invalidUrl in invalidUrls)
            {
                Assert.False(SpeechletRequestSignatureVerifier.VerifyCertificateUrl(invalidUrl));
            }
        }
        public async Task <SpeechletRequestEnvelope> GetRequestAsync(string content, string chainUrl, string signature)
        {
            var validationResult = SpeechletRequestValidationResult.OK;

            if (string.IsNullOrEmpty(chainUrl))
            {
                validationResult |= SpeechletRequestValidationResult.NoCertHeader;
            }

            if (string.IsNullOrEmpty(signature))
            {
                validationResult |= SpeechletRequestValidationResult.NoSignatureHeader;
            }

            // attempt to verify signature only if we were able to locate certificate and signature headers
            if (validationResult == SpeechletRequestValidationResult.OK)
            {
                var alexaBytes = Encoding.UTF8.GetBytes(content);

                if (!await SpeechletRequestSignatureVerifier.VerifyRequestSignatureAsync(alexaBytes, signature, chainUrl))
                {
                    validationResult |= SpeechletRequestValidationResult.InvalidSignature;
                }
            }

            SpeechletRequestEnvelope result = null;

            try {
                result = SpeechletRequestEnvelope.FromJson(content);
            }
            catch (Exception ex)
                when(ex is Newtonsoft.Json.JsonReaderException || ex is InvalidCastException || ex is FormatException)
                {
                    validationResult |= SpeechletRequestValidationResult.InvalidJson;
                }

            var success = false;

            // attempt to verify timestamp only if we were able to parse request body
            if (result != null)
            {
                var now = DateTime.UtcNow; // reference time for this request

                if (!SpeechletRequestTimestampVerifier.VerifyRequestTimestamp(result, now))
                {
                    validationResult |= SpeechletRequestValidationResult.InvalidTimestamp;
                }

                success = speechlet?.OnRequestValidation(validationResult, now, result) ?? (validationResult == SpeechletRequestValidationResult.OK);
            }

            if (!success)
            {
                throw new SpeechletValidationException(validationResult);
            }

            return(result);
        }
 public void VerifyUrl(
     string urlToValidate,
     bool isValid,
     string reason)
 {
     Assert.IsTrue(
         SpeechletRequestSignatureVerifier.IsValidUrl(urlToValidate) == isValid,
         reason);
 }
        /// <summary>
        /// Processes Alexa request AND validates request signature
        /// </summary>
        /// <param name="httpRequest"></param>
        /// <returns></returns>
        public async virtual Task <HttpResponseMessage> GetResponseAsync(HttpRequestMessage httpRequest)
        {
            if (!httpRequest.Headers.Contains(Sdk.SIGNATURE_CERT_URL_REQUEST_HEADER) ||
                !httpRequest.Headers.Contains(Sdk.SIGNATURE_REQUEST_HEADER))
            {
                return(new HttpResponseMessage(HttpStatusCode.BadRequest)); // Request signature absent
            }

            string chainUrl  = httpRequest.Headers.GetValues(Sdk.SIGNATURE_CERT_URL_REQUEST_HEADER).First();
            string signature = httpRequest.Headers.GetValues(Sdk.SIGNATURE_REQUEST_HEADER).First();

            var alexaBytes = await httpRequest.Content.ReadAsByteArrayAsync();

            Debug.WriteLine(httpRequest.ToLogString());
            if (!(await SpeechletRequestSignatureVerifier.VerifyRequestSignatureAsync(alexaBytes, signature, chainUrl)))
            {
                return(new HttpResponseMessage(HttpStatusCode.BadRequest)); // Failed signature verification
            }

            var    alexaContent  = UTF8Encoding.UTF8.GetString(alexaBytes);
            string alexaResponse = await ProcessRequestAsync(alexaContent);

            HttpResponseMessage httpResponse;

            if (alexaResponse == null)
            {
                httpResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }
            else if (alexaResponse == String.Empty)
            {
                httpResponse = new HttpResponseMessage(HttpStatusCode.BadRequest);
            }
            else
            {
                httpResponse         = new HttpResponseMessage(HttpStatusCode.OK);
                httpResponse.Content = new StringContent(alexaResponse, Encoding.UTF8, "application/json");
                Debug.WriteLine(httpResponse.ToLogString());
            }

            return(httpResponse);
        }
        /// <summary>
        /// Processes Alexa request AND validates request signature
        /// </summary>
        /// <param name="httpRequest"></param>
        /// <returns></returns>
        public virtual HttpResponseMessage GetResponse(HttpRequestMessage httpRequest)
        {
            SpeechletRequestValidationResult validationResult = SpeechletRequestValidationResult.OK;
            DateTime now = DateTime.UtcNow; // reference time for this request

            string chainUrl = null;

            if (!httpRequest.Headers.Contains(Sdk.SIGNATURE_CERT_URL_REQUEST_HEADER) ||
                String.IsNullOrEmpty(chainUrl = httpRequest.Headers.GetValues(Sdk.SIGNATURE_CERT_URL_REQUEST_HEADER).First()))
            {
                validationResult = validationResult | SpeechletRequestValidationResult.NoCertHeader;
            }

            string signature = null;

            if (!httpRequest.Headers.Contains(Sdk.SIGNATURE_REQUEST_HEADER) ||
                String.IsNullOrEmpty(signature = httpRequest.Headers.GetValues(Sdk.SIGNATURE_REQUEST_HEADER).First()))
            {
                validationResult = validationResult | SpeechletRequestValidationResult.NoSignatureHeader;
            }

            var alexaBytes = AsyncHelpers.RunSync <byte[]>(() => httpRequest.Content.ReadAsByteArrayAsync());

            Debug.WriteLine(httpRequest.ToLogString());

            // attempt to verify signature only if we were able to locate certificate and signature headers
            if (validationResult == SpeechletRequestValidationResult.OK)
            {
                if (!SpeechletRequestSignatureVerifier.VerifyRequestSignature(alexaBytes, signature, chainUrl))
                {
                    validationResult = validationResult | SpeechletRequestValidationResult.InvalidSignature;
                }
            }

            SpeechletRequestEnvelope alexaRequest = null;

            try {
                var alexaContent = UTF8Encoding.UTF8.GetString(alexaBytes);
                alexaRequest = SpeechletRequestEnvelope.FromJson(alexaContent);
            }
            catch (Newtonsoft.Json.JsonReaderException) {
                validationResult = validationResult | SpeechletRequestValidationResult.InvalidJson;
            }
            catch (InvalidCastException) {
                validationResult = validationResult | SpeechletRequestValidationResult.InvalidJson;
            }

            // attempt to verify timestamp only if we were able to parse request body
            if (alexaRequest != null)
            {
                if (!SpeechletRequestTimestampVerifier.VerifyRequestTimestamp(alexaRequest, now))
                {
                    validationResult = validationResult | SpeechletRequestValidationResult.InvalidTimestamp;
                }
            }

            if (alexaRequest == null || !OnRequestValidation(validationResult, now, alexaRequest))
            {
                return(new HttpResponseMessage(HttpStatusCode.BadRequest)
                {
                    ReasonPhrase = validationResult.ToString()
                });
            }

            string alexaResponse = DoProcessRequest(alexaRequest);

            HttpResponseMessage httpResponse;

            if (alexaResponse != null)
            {
                httpResponse         = new HttpResponseMessage(HttpStatusCode.OK);
                httpResponse.Content = new StringContent(alexaResponse, Encoding.UTF8, "application/json");
                // Debug.WriteLine(httpResponse.ToLogString());
            }
            else
            {
                httpResponse = new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }

            return(httpResponse);
        }
Exemple #6
0
 public AlexaScheduleSkillController(AlexaTwinRinksSkillRequestProcessor service, SpeechletRequestSignatureVerifier verifier)
 {
     _service     = service;
     _reqVerifier = verifier;
 }
Exemple #7
0
        /// <summary>
        /// Processes Alexa request AND validates request signature
        /// </summary>
        /// <returns></returns>
        public virtual string GetResponse(Dictionary <string, string[]> Headers, byte[] Content, out HttpStatusCode HttpStatusCode)
        {
            SpeechletRequestValidationResult validationResult = SpeechletRequestValidationResult.OK;
            DateTime now = DateTime.UtcNow; // reference time for this request

            string chainUrl = null;

            if (!Headers.ContainsKey(Sdk.SIGNATURE_CERT_URL_REQUEST_HEADER) ||
                String.IsNullOrEmpty(chainUrl = Headers[Sdk.SIGNATURE_CERT_URL_REQUEST_HEADER].First()))
            {
                validationResult = validationResult | SpeechletRequestValidationResult.NoCertHeader;
            }

            string signature = null;

            if (!Headers.ContainsKey(Sdk.SIGNATURE_REQUEST_HEADER) ||
                String.IsNullOrEmpty(signature = Headers[Sdk.SIGNATURE_REQUEST_HEADER].First()))
            {
                validationResult = validationResult | SpeechletRequestValidationResult.NoSignatureHeader;
            }

            // attempt to verify signature only if we were able to locate certificate and signature headers
            if (validationResult == SpeechletRequestValidationResult.OK)
            {
                if (!SpeechletRequestSignatureVerifier.VerifyRequestSignature(Content, signature, chainUrl))
                {
                    validationResult = validationResult | SpeechletRequestValidationResult.InvalidSignature;
                }
            }

            SpeechletRequestEnvelope alexaRequest = null;

            try
            {
                var alexaContent = UTF8Encoding.UTF8.GetString(Content);
                alexaRequest = SpeechletRequestEnvelope.FromJson(alexaContent);
            }
            catch (Newtonsoft.Json.JsonReaderException)
            {
                validationResult = validationResult | SpeechletRequestValidationResult.InvalidJson;
            }
            catch (InvalidCastException)
            {
                validationResult = validationResult | SpeechletRequestValidationResult.InvalidJson;
            }

            // attempt to verify timestamp only if we were able to parse request body
            if (alexaRequest != null)
            {
                if (!SpeechletRequestTimestampVerifier.VerifyRequestTimestamp(alexaRequest, now))
                {
                    validationResult = validationResult | SpeechletRequestValidationResult.InvalidTimestamp;
                }
            }

            if (alexaRequest == null || !OnRequestValidation(validationResult, now, alexaRequest))
            {
                HttpStatusCode = HttpStatusCode.BadRequest;
                return(validationResult.ToString());
            }

            string alexaResponse = DoProcessRequest(alexaRequest);

            if (alexaResponse == null)
            {
                HttpStatusCode = HttpStatusCode.InternalServerError;
                return(null);
            }
            else
            {
                HttpStatusCode = HttpStatusCode.OK;
                return(alexaResponse);
            }
        }
        /// <summary>
        ///     Processes Alexa request AND validates request signature
        /// </summary>
        /// <param name="httpRequest"></param>
        /// <returns></returns>
        public virtual TResponse GetResponse(T httpRequest)
        {
            var validationResult = SpeechletRequestValidationResult.OK;
            var now = DateTime.UtcNow; // reference time for this request

            string chainUrl = null;

            if (!httpRequest.Headers.Contains(Sdk.SIGNATURE_CERT_URL_REQUEST_HEADER) ||
                string.IsNullOrEmpty(
                    chainUrl = httpRequest.Headers.GetValue(Sdk.SIGNATURE_CERT_URL_REQUEST_HEADER).First()))
            {
                validationResult = validationResult | SpeechletRequestValidationResult.NoCertHeader;
            }

            string signature = null;

            if (!httpRequest.Headers.Contains(Sdk.SIGNATURE_REQUEST_HEADER) ||
                string.IsNullOrEmpty(signature = httpRequest.Headers.GetValue(Sdk.SIGNATURE_REQUEST_HEADER).First()))
            {
                validationResult = validationResult | SpeechletRequestValidationResult.NoSignatureHeader;
            }

            var alexaBytes   = AsyncHelpers.RunSync(() => httpRequest.Content.ReadAsByteArrayAsync());
            var alexaContent = Encoding.UTF8.GetString(alexaBytes);

            //Debug.WriteLine(httpRequest.ToLogString()); //todo

            // attempt to verify signature only if we were able to locate certificate and signature headers
            if (validationResult == SpeechletRequestValidationResult.OK)
            {
                if (!SpeechletRequestSignatureVerifier.VerifyRequestSignature(alexaBytes, signature, chainUrl))
                {
                    validationResult = validationResult | SpeechletRequestValidationResult.InvalidSignature;
                }
            }

            SpeechletRequestEnvelope alexaRequest = null;

            try
            {
                alexaRequest = SpeechletRequestEnvelope.FromJson(alexaContent);
            }
            catch (JsonReaderException)
            {
                validationResult = validationResult | SpeechletRequestValidationResult.InvalidJson;
            }
            catch (InvalidCastException)
            {
                validationResult = validationResult | SpeechletRequestValidationResult.InvalidJson;
            }

            // attempt to verify timestamp only if we were able to parse request body
            if (alexaRequest != null)
            {
                if (!SpeechletRequestTimestampVerifier.VerifyRequestTimestamp(alexaRequest, now))
                {
                    validationResult = validationResult | SpeechletRequestValidationResult.InvalidTimestamp;
                }
            }

            if ((alexaRequest == null) || !OnRequestValidation(validationResult, now, alexaRequest))
            {
                var responseFactory = new TResponseFactory();
                return(responseFactory.BadRequest(validationResult.ToString()));
            }

            var alexaResponse = DoProcessRequest(alexaRequest);

            if (alexaResponse == null)
            {
                var responseFactory = new TResponseFactory();
                return(responseFactory.InternalServerError());
            }
            else
            {
                var responseFactory = new TResponseFactory();
                return(responseFactory.Ok(alexaResponse));
            }
        }