Webservice Support and Framework Adapters

ask-sdk-webservice-support package

ask_sdk_webservice_support.verifier_constants module

ask_sdk_webservice_support.verifier_constants.SIGNATURE_CERT_CHAIN_URL_HEADER = 'SignatureCertChainUrl'

Header key to be used, to retrieve request header that contains the URL for the certificate chain needed to verify the request signature. For more info, check link.

ask_sdk_webservice_support.verifier_constants.SIGNATURE_HEADER = 'Signature'

Header key to be used, to retrieve request header that contains the request signature. For more info, check link.

ask_sdk_webservice_support.verifier_constants.CERT_CHAIN_URL_PROTOCOL = 'https'

Case insensitive protocol to be checked on signature certificate url. For more info, check link.

ask_sdk_webservice_support.verifier_constants.CERT_CHAIN_URL_HOSTNAME = 's3.amazonaws.com'

Case insensitive hostname to be checked on signature certificate url. For more info, check link.

ask_sdk_webservice_support.verifier_constants.CERT_CHAIN_URL_STARTPATH = '/echo.api/'

Path presence to be checked on signature certificate url. For more info, check link.

ask_sdk_webservice_support.verifier_constants.CERT_CHAIN_URL_PORT = 443

Port to be checked on signature certificate url. For more info, check link.

ask_sdk_webservice_support.verifier_constants.CERT_CHAIN_DOMAIN = 'echo-api.amazon.com'

Domain presence check in Subject Alternative Names (SANs) of signing certificate. For more info, check link.

ask_sdk_webservice_support.verifier_constants.CHARACTER_ENCODING = 'utf-8'

Character encoding used in the request.

ask_sdk_webservice_support.verifier_constants.DEFAULT_TIMESTAMP_TOLERANCE_IN_MILLIS = 150000

Default allowable tolerance in request timestamp. For more info, check link.

ask_sdk_webservice_support.verifier_constants.MAX_TIMESTAMP_TOLERANCE_IN_MILLIS = 3600000

Maximum allowable tolerance in request timestamp. For more info, check link.

ask_sdk_webservice_support.verifier module

exception ask_sdk_webservice_support.verifier.VerificationException

Bases: ask_sdk_runtime.exceptions.AskSdkException

Class for exceptions raised during Request verification.

args
with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class ask_sdk_webservice_support.verifier.AbstractVerifier

Bases: object

Abstract verifier class for implementing custom verifiers.

verify(headers, serialized_request_env, deserialized_request_env)

Abstract verify method that verifies and validates inputs.

Custom verifiers should implement this method, to validate the headers and body of the input POST request. The method returns a VerificationException if the validation fails, or succeeds silently.

Parameters:
  • headers (Dict[str, Any]) – headers of the input POST request
  • serialized_request_env (str) – raw request envelope in the input POST request
  • deserialized_request_env (ask_sdk_model.request_envelope.RequestEnvelope) – deserialized request envelope instance of the input POST request
Raises:

VerificationException if verification fails

class ask_sdk_webservice_support.verifier.RequestVerifier(signature_cert_chain_url_key='SignatureCertChainUrl', signature_key='Signature', padding=<cryptography.hazmat.primitives.asymmetric.padding.PKCS1v15 object>, hash_algorithm=<cryptography.hazmat.primitives.hashes.SHA1 object>)

Bases: ask_sdk_webservice_support.verifier.AbstractVerifier

Verifier that performs request signature verification.

This is a concrete implementation of AbstractVerifier class, handling the request signature verification of the input request. This verifier uses the Cryptography module x509 functions to validate the signature chain in the input request. The verification follows the mechanism explained here : https://developer.amazon.com/docs/custom-skills/host-a-custom-skill-as-a-web-service.html#checking-the-signature-of-the-request

The constructor takes the header key names for retrieving Signature Certificate Chain and Signature. They are defaulted to the header names present in the ask_sdk_webservice_support.verifier_constants. Additionally, one can also provide the Padding and the Hash Algorithm function that is used to verify the input body.

The verify method retrieves the Signature Certificate Chain URL, validates the URL, retrieves the chain from the URL, validates the signing certificate, extract the public key, base64 decode the Signature and verifies if the hash value of the request body matches with the decrypted signature.

verify(headers, serialized_request_env, deserialized_request_env)

Verify if the input request signature and the body matches.

The verify method retrieves the Signature Certificate Chain URL, validates the URL, retrieves the chain from the URL, validates the signing certificate, extract the public key, base64 decode the Signature and verifies if the hash value of the request body matches with the decrypted signature.

Parameters:
  • headers (Dict[str, Any]) – headers of the input POST request
  • serialized_request_env (str) – raw request envelope in the input POST request
  • deserialized_request_env (ask_sdk_model.request_envelope.RequestEnvelope) – deserialized request envelope instance of the input POST request
Raises:

VerificationException if headers doesn’t exist or verification fails

class ask_sdk_webservice_support.verifier.TimestampVerifier(tolerance_in_millis=150000)

Bases: ask_sdk_webservice_support.verifier.AbstractVerifier

Verifier that performs request timestamp verification.

This is a concrete implementation of AbstractVerifier class, handling the request timestamp verification of the input request. The verification follows the mechanism explained here : https://developer.amazon.com/docs/custom-skills/host-a-custom-skill-as-a-web-service.html#timestamp

The constructor takes the tolerance value in milliseconds, that is the maximum tolerance limit the input request can have, with the current timestamp.

The verify method retrieves the request timestamp and check if it falls in the limit set by the tolerance.

verify(headers, serialized_request_env, deserialized_request_env)

Verify if the input request timestamp is in tolerated limits.

The verify method retrieves the request timestamp and check if it falls in the limit set by the tolerance, by checking with the current timestamp in UTC.

Parameters:
  • headers (Dict[str, Any]) – headers of the input POST request
  • serialized_request_env (str) – raw request envelope in the input POST request
  • deserialized_request_env (ask_sdk_model.request_envelope.RequestEnvelope) – deserialized request envelope instance of the input POST request
Raises:

VerificationException if difference between local timestamp and input request timestamp is more than specific tolerance limit

ask_sdk_webservice_support.webservice_handler module

class ask_sdk_webservice_support.webservice_handler.WebserviceSkillHandler(skill, verify_signature=True, verify_timestamp=True, verifiers=None)

Bases: object

Skill Handler for skill as webservice.

This class can be used by skill developers when they want their skills to be deployed as a web service, rather than using AWS Lambda.

The class constructor takes in a custom skill instance that is used for routing the input request. The boolean verify_signature variable configures if the request signature is verified for each input request. The boolean verify_timestamp configures if the request timestamp is verified for each input request. Additionally, an optional list of verifiers can also be provided, to be applied on the input request.

The verify_request_and_dispatch method provides the dispatch functionality that can be used as an entry point for skill invocation as web service.

verify_request_and_dispatch(http_request_headers, http_request_body)

Entry point for webservice skill invocation.

This method takes in the input request headers and request body, handles the deserialization of the input request to the ask_sdk_model.request_envelope.RequestEnvelope object, run the input through registered verifiers, invoke the skill and return the serialized response from the skill invocation.

Parameters:
  • http_request_headers (Dict[str, Any]) – Request headers of the input request to the webservice
  • http_request_body (str) – Raw request body of the input request to the webservice
Returns:

Serialized response object returned by the skill instance, when invoked with the input request

Return type:

str

Raises:

ask_sdk_core.exceptions.AskSdkException when skill deserialization, verification, invocation or serialization fails


flask-ask-sdk package

flask_ask_sdk.skill_adapter module

class flask_ask_sdk.skill_adapter.SkillAdapter(skill, skill_id, verifiers=None, app=None)

Bases: object

Provides a base interface to register skill and dispatch the request.

The class constructor takes a ask_sdk_core.skill.CustomSkill instance, the skill id, an optional list of ask_sdk_webservice_support.verifier.AbstractVerifier instances and an optional flask application. One can also use the init_app() method, to pass in a flask.Flask application instance, to instantiate the config values and the webservice handler.

The dispatch_request() function can be used to map the input request to the skill invocation. The register() function can also be used alternatively, to register the dispatch_request() function to the provided route.

By default, the ask_sdk_webservice_support.verifier.RequestVerifier and ask_sdk_webservice_support.verifier.TimestampVerifier instances are added to the skill verifier list. To disable this, set the VERIFY_SIGNATURE_APP_CONFIG and VERIFY_TIMESTAMP_APP_CONFIG app configuration values to False.

An instance of the extension is added to the application extensions mapping, under the key EXTENSION_NAME. Since multiple skills can be configured on different routes in the same application, through multiple extension instances, each extension is added as a skill id mapping under the app extensions EXTENSION_NAME dictionary.

For example, to use this class with a skill created using ask-sdk-core:

from flask import Flask
from ask_sdk_core.skill_builder import SkillBuilder
from flask_ask_sdk.skill_adapter import SkillAdapter

app = Flask(__name__)
skill_builder = SkillBuilder()
# Register your intent handlers to skill_builder object

skill_adapter = SkillAdapter(
    skill=skill_builder.create(), skill_id=<SKILL_ID>, app=app)

@app.route("/"):
def invoke_skill:
    return skill_adapter.dispatch_request()

Alternatively, you can also use the register method:

from flask import Flask
from ask_sdk_core.skill_builder import SkillBuilder
from flask_ask_sdk.skill_adapter import SkillAdapter

app = Flask(__name__)
skill_builder = SkillBuilder()
# Register your intent handlers to skill_builder object

skill_adapter = SkillAdapter(
    skill=skill_builder.create(), skill_id=<SKILL_ID>, app=app)

skill_adapter.register(app=app, route="/")
init_app(app)

Register the extension on the given Flask application.

Use this function only when no Flask application was provided in the app keyword argument to the constructor of this class.

The function sets True defaults for VERIFY_SIGNATURE_APP_CONFIG and VERIFY_TIMESTAMP_APP_CONFIG configurations. It adds the skill id: self instance mapping to the application extensions, and creates a ask_sdk_webservice_support.webservice_handler.WebserviceHandler instance, for request verification and dispatch.

Parameters:app (flask.Flask) – A flask.Flask application instance
Return type:None
dispatch_request()

Method that handles request verification and routing.

This method can be used as a function to register on the URL rule. The request is verified through the registered list of verifiers, before invoking the request handlers. The method returns a JSON response for the Alexa service to respond to the request.

Returns:The skill response for the input request
Return type:flask.Response
Raises:werkzeug.exceptions.MethodNotAllowed if the method is invoked for other than HTTP POST request. werkzeug.exceptions.BadRequest if the verification fails. werkzeug.exceptions.InternalServerError for any internal exception.
register(app, route, endpoint=None)

Method to register the routing on the app at provided route.

This is a utility method, that can be used for registering the dispatch_request on the provided flask.Flask application at the provided URL route.

Parameters:
  • app (flask.Flask) – A flask.Flask application instance
  • route (str) – The URL rule where the skill dispatch has to be registered
  • endpoint (str) – The endpoint for the registered URL rule. This can be used to set multiple skill endpoints on same app.
Return type:

None

Raises:

TypeError if app or route` is not provided or is of an invalid type

flask_ask_sdk.skill_adapter.EXTENSION_NAME = 'ASK_SDK_SKILL_ADAPTER'

Extension name used for saving extension instance in app.extensions


django-ask-sdk package

django_ask_sdk.skill_adapter module

class django_ask_sdk.skill_adapter.SkillAdapter(skill, verify_signature=True, verify_timestamp=True, verifiers=None)

Bases: django.views.generic.base.View

Provides a base interface to register skill and dispatch the request.

The class constructor takes a ask_sdk_core.skill.CustomSkill instance, an optional verify_request boolean, an optional verify_timestamp boolean and an optional list of ask_sdk_webservice_support.verifier.AbstractVerifier instances.

The post() function is the only available method on the view, that intakes the input POST request from Alexa, verifies the request and dispatch it to the skill.

By default, the ask_sdk_webservice_support.verifier.RequestVerifier and ask_sdk_webservice_support.verifier.TimestampVerifier instances are added to the skill verifier list. To disable this, set the verify_request and verify_timestamp input arguments to False respectively.

For example, if you developed a skill using an instance of ask_sdk_core.skill_builder.SkillBuilder or it’s subclasses, then to register it as an endpoint in your django app example, you can add the following in example.urls.py:

import skill
from django_ask_sdk.skill_response import SkillAdapter

view = SkillAdapter.as_view(skill=skill.sb.create())

urlpatterns = [
    path("/myskill", view, name='index')
]
skill = None
verify_signature = None
verify_timestamp = None
verifiers = None
dispatch(request, *args, **kwargs)

Inspect the HTTP method and delegate to the view method.

This is the default implementation of the django.views.View method, which will inspect the HTTP method in the input request and delegate it to the corresponding method in the view. The only allowed method on this view is post.

Parameters:request (django.http.HttpRequest) – The input request sent to the view
Returns:The response from the view
Return type:django.http.HttpResponse
Raises:django.http.HttpResponseNotAllowed if the method is invoked for other than HTTP POST request. django.http.HttpResponseBadRequest if the request verification fails. django.http.HttpResponseServerError for any internal exception.
post(request, *args, **kwargs)

The method that handles HTTP POST request on the view.

This method is called when the view receives a HTTP POST request, which is generally the request sent from Alexa during skill invocation. The request is verified through the registered list of verifiers, before invoking the request handlers. The method returns a django.http.JsonResponse in case of successful skill invocation.

Parameters:request (django.http.HttpRequest) – The input request sent by Alexa to the skill
Returns:The response from the skill to Alexa
Return type:django.http.JsonResponse
Raises:django.http.HttpResponseBadRequest if the request verification fails. django.http.HttpResponseServerError for any internal exception.
classmethod as_view(**initkwargs)

Main entry point for a request-response process.

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
http_method_not_allowed(request, *args, **kwargs)
options(request, *args, **kwargs)

Handle responding to requests for the OPTIONS HTTP verb.

setup(request, *args, **kwargs)

Initialize attributes shared by all view methods.

django_ask_sdk.skill_adapter.SIGNATURE_CERT_CHAIN_URL_KEY = 'HTTP_SIGNATURECERTCHAINURL'

Signature Certificate Chain URL header key in Django HTTP Headers. This is different from the header key provided by Alexa, because of Django’s HTTP Meta headers.

django_ask_sdk.skill_adapter.SIGNATURE_KEY = 'HTTP_SIGNATURE'

Signature header key in Django HTTP Headers. This is different from the header key provided by Alexa, because of Django’s HTTP Meta headers.