Host a Custom Skill as a Web Service
You can build a custom skill for Alexa by implementing a web service that accepts requests from and sends responses to the Alexa service in the cloud. You can build your web service using any programming language, as long as the service meets the following requirements.
These requirements apply only to skills that use a custom web service. Alternatively, you can implement your skill as an AWS Lambda function using AWS Lambda from Amazon Web Services. For more information, see Host a Custom Skill as an AWS Lambda Function.
- Requirements for your web service
- About the SSL options
- Verify that the request was sent by Alexa
- Related Topics
Requirements for your web service
To handle requests sent by Alexa, your web service must meet the following requirements:
- The service must be accessible over the internet.
- The service must accept HTTP requests on port 443.
- The service must support HTTP over SSL/TLS, using an Amazon-trusted certificate. Your web service's domain name must be in the
Subject Alternative Names
(SANs) section of the certificate. For testing, you can provide a self-signed certificate. For more information, see About the SSL Options. - The service must verify that incoming requests come from Alexa. For more information, see Verify that the request was sent by Alexa.
- The service must adhere to the Alexa Skills Kit interface.
unrecognized_name
warning when the server is not configured with a ServerName
or ServerAlias
in the configuration files. This prevents the Alexa service from sending requests to your server when users use your skill. Make sure you upgrade Apache HTTP Server to version 2.4.10 or higher, or else add ServerName
or ServerAlias
to your server's configuration file.About the SSL options
When Alexa communicates with your skill's web service, user requests and corresponding responses are transmitted over the internet. To protect the confidentiality and integrity of this data, Alexa strictly enforces that HTTP connections are secured using SSL/TLS.
This means that the web service for a skill that is published to users must present a valid and trusted certificate when the connection is established, and must possess the corresponding private key.
You need to specify which type of SSL certificate your web service uses. You specify the type of certificate in the Alexa Skills Kit developer console, on the Build page, in the Endpoint section. Choose the appropriate option based on the type of SSL certificate that your web service uses, as described in the following list. If you're not sure which to choose, you might need to check with your hosting provider to determine which type of certificate your web service uses.
- If your web service uses a certificate signed by an Amazon-trusted certificate authority, choose My development endpoint has a certificate from a trusted certificate authority.
- If your web service uses a wildcard certificate, select My development endpoint is a sub-domain of a domain that has a wildcard certificate from a certificate authority. A wildcard certificate provides SSL for multiple sub-domains. You can use this type of certificate as long as it is signed by an Amazon-trusted certificate authority.
-
For testing, your web service can use a self-signed certificate. In this case you must create the certificate yourself, upload it to the Alexa Skills Kit developer console, and configure your web service to present this certificate when the Alexa service connects to your web service. For more information, see Configure Your Web Service to Use a Self-signed Certificate.
Note: You can use a self-signed certificate only for testing. To publish your skill, your web service must use a certificate signed by an Amazon-trusted certificate authority.
Verify that the request was sent by Alexa
Requests that the Alexa service sends to your web service are transmitted over the internet. To protect your web service from potential attackers, your web service must verify that incoming requests are sent by Alexa. Requests that don't come from Alexa must be rejected. This is required to get your skill certified and published to users. Web services that accept unsigned or out-of-date requests will not pass certification.
If you build your web service using JavaScript, Java, or Python, you can use the Alexa Skills Kit SDKs (ASK SDKs) for Node.js, Java, or Python to verify that requests to your web service come from Alexa. The SDKs also provide code that can help make it easier to build a web service.
For more information about using the SDKs to build a custom web service, see:
If you don't use the ASK SDKs, you must write code to verify each incoming request. For more information, see Manually verify that the request was sent by Alexa.
Use the ASK SDK for Node.js
The ASK SDK for Node.js provides support for building a custom web service in the ask-sdk-express-adapter
package. You can use the package to help verify that Alexa sent the requests that your web service receives.
In addition, the SDK provides extensions for Express.js, commonly used to build web applications in Node.js. You can use the extensions to help you build the web service for your skill.
For more information and code examples, see Host a Custom Skill as a Web Service in the ASK SDK for Node.js documentation.
Use the ASK SDK for Java
The ASK SDK for Java provides support for building a custom web service in the form of a Java servlet. If you build your web service using Java and don't want to use the servlet, you can still use the SDK to help verify that Alexa sent the requests that your web service receives.
For more information and code examples, see Host a Custom Skill as a Web Service in the ASK SDK for Java documentation.
Use the ASK SDK for Python
The ASK SDK for Python provides support for building a custom web service in the ask-sdk-webservice-support
package. You can use this package to help verify that Alexa sent the requests that your web service receives.
In addition, the SDK provides extensions for Flask and Django, two frameworks commonly used to build web applications in Python. You can use the extensions to help you build the web service for your skill.
For more information and code examples, see Host a Custom Skill as a Web Service in the ASK SDK for Python documentation.
Manually verify that the request was sent by Alexa
To manually verify that a request came from the Alexa service, you must write code that performs the following steps:
- Check the request signature to verify the authenticity of the request. Alexa signs all HTTPS requests. For more information, see Check the request signature.
- Check the request timestamp to make sure that the request is not an old one being sent as part of a replay attack. For more information, see Check the request timestamp.
400 Bad Request
.Check the request signature
Requests that Alexa sends to your web service include two HTTP headers that you must use to check the request signature:
SignatureCertChainUrl
Signature-256
Signature
header against the SHA-1 hash of the HTTP request body, we recommend that you update your implementation to validate the Signature-256
header against the SHA-256 hash of the HTTP request body.To check and validate the request signature:
-
Verify the URL in the
SignatureCertChainUrl
header to make sure that it matches the format that Alexa uses. This can help to protect against requests that attempt to make your web service download malicious files.-
Normalize the URL in the
SignatureCertChainUrl
header by removing dot segments and duplicate slashes and fragment. For example, normalize the following path:https://s3.amazonaws.com/echo.api/../echo.api/echo-api-cert.pem
to:
https://s3.amazonaws.com/echo.api/echo-api-cert.pem
-
Make sure that the URL meets all of the following criteria:
- The protocol is
https
(not case sensitive). - The hostname is
s3.amazonaws.com
(not case sensitive). - The path begins with
/echo.api/
(case sensitive). - If a port is specified in the URL, the port is
443
.
The following are examples of correctly formatted URLs:
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
The following are examples of invalid URLs:
http://s3.amazonaws.com/echo.api/echo-api-cert.pem
(invalid protocol)https://notamazon.com/echo.api/echo-api-cert.pem
(invalid hostname)https://s3.amazonaws.com/EcHo.aPi/echo-api-cert.pem
(invalid path)https://s3.amazonaws.com/invalid.path/echo-api-cert.pem
(invalid path)https://s3.amazonaws.com:563/echo.api/echo-api-cert.pem
(invalid port)
If the URL does not meet all of these criteria, do not proceed to the next step.
- The protocol is
-
-
Download the PEM-encoded X.509 certificate chain using the URL specified in the
SignatureCertChainUrl
header in the request. This chain is provided at runtime so that it can be updated periodically. Your web service should be resilient to different URLs with different content. - This certificate chain you downloaded in the preceding step is composed of the following, in order:
- The Amazon signing certificate.
- One or more additional certificates that create a chain of trust to a root certificate of a certificate authority (CA).
Confirm the validity of the signing certificate by completing the following steps:
- Check the
Not Before
andNot After
dates of the signing certificate to make sure that it is not expired. - Make sure the domain name
echo-api.amazon.com
is present in theSubject Alternative Names
(SANs) section of the signing certificate. - Validate that all certificates in the chain combine to create a chain of trust to a trusted root CA certificate.
-
After you confirm the validity of the signing certificate, extract the public key from it.
-
Base64-decode the value of the
Signature-256
header in the request to obtain the encrypted signature. -
Use the public key that you extracted from the signing certificate to decrypt the encrypted signature to produce the asserted hash value.
-
Generate a SHA-256 hash value from the full HTTP request body to produce the derived hash value.
- Compare the asserted hash value and derived hash values to ensure that they match. If they do not match, discard the request.
Check the request timestamp
Every request that Alexa sends to your web service includes a timestamp in the request body. The timestamp is part of the signed portion of the request, so it cannot be modified without also invalidating the request signature. Use this timestamp to verify the freshness of the request before sending a response. This can help protect your web service from attempted replay attacks in which an attacker acquires a properly signed request and then repeatedly resends it to disrupt your web service.
Your web service should allow a tolerance of no more than 150 seconds (two and a half minutes). This means that your service should only process requests in which the timestamp
is within 150 seconds of the current time. If the timestamp
differs from the current time by more than 150 seconds, discard the request. If your web service processes requests that are more than 150 seconds out of sync with the current time, your skill cannot be certified and published to users.
The timestamp
is part of the request
object in the JSON body of the request. For example:
{
"version": "1.0",
"session": {
"new": true,
...
},
"request": {
"type": "LaunchRequest",
"timestamp": "string",
"requestId": "string"
}
}
The timestamp
value is an ISO 8601 formatted string, for example 2019-05-13T12:34:56Z
. Your code must convert the string into a date object, then verify that it is within the tolerance that your web service allows (no more than 150 seconds from the current time). Use an HTTP error code, such as 400 Bad Request
, to reject requests in which the timestamp
falls outside the tolerance.
Related Topics
- Build Skills in the Alexa Developer Console
- Configure Your Web Service to Use a Self-signed Certificate
- Host a Custom Skill as an AWS Lambda Function
Last updated: Jan 26, 2024