Use Personal AWS Resources with Your Alexa-Hosted Skill


When you create an Alexa-hosted skill, Alexa stores your code and resources on Amazon Web Services (AWS) for you. You get access to three AWS Lambda endpoints, an Amazon S3 bucket for media storage, and an Amazon DynamoDB table for persisting data to DynamoDB. For details about the AWS resources for an Alexa-hosted skill, see About Alexa-hosted Skills.

If your skill requires additional AWS services, or if your usage exceeds the usage limits, you can provision the additional resources in your personal AWS account.

With the AWS Lambda execution role Alexa Resource Name (ARN), you can seamlessly use resources on a personal AWS account to expand the functionality of your Alexa-hosted skill. For example, you can connect your Alexa-hosted skill to your own Amazon DynamoDB table.

Set up permissions

To enable your Alexa-hosted skill to use resources in your personal AWS account, create an AWS Identity and Access Management (IAM) role to allow access to the resource from your Alexa-hosted skill. For details about creating AWS IAM roles, see the AWS Identity and Access Management User Guide.

To get your Alexa skill ARN

  1. Open the Alexa developer console and log in.
  2. In the console, open your Alexa-hosted skill.
  3. In the code editor, click the icon for Link your personal AWS resources.
  4. Copy the ARN.

To create an AWS IAM role

  1. Open the AWS management console and log in.
  2. In the console, open the Identity and Access Management (IAM) dashboard.
  3. In the IAM dashboard, click Roles.
  4. On the Roles page, click Create role.
  5. On the Create role page, under Select type of trusted entity, select AWS service.
  6. In the Choose a use case section, under Common use cases, select one of the common use cases.
    -Or-
    Under Or select a service to view its use cases, select one of the services from the list, and then under select your use case, select a use case.
    For example, select DynamoDB from the list of services, and then select Amazon DynamoDB Accelerator (DAX) - DynamoDB access from the list of use cases.
  7. Click Next: Permissions.
  8. Choose one or more policies to attach to your new role, and then click Next: Tags.
    For example, select the AmazonDynamoDBFullAccess policy for full access to your DynamoDB table.
  9. Click Next: Review, and enter the name and description of your role.
  10. Click Create role.

To add your Alexa skill ARN to the role

  1. In the IAM dashboard, click Roles.
  2. On the Roles page, click the name of the role you just created, and then click the Trust relationships tab.
  3. Click Edit trust relationship.
  4. Add an entry for the AWS Lambda Role Execution ARN from your Alexa-hosted skill to the Statement property and include the sts:AssumeRole action as shown in the following example. Don't overwrite other existing entries in the Statement property.

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {"AWS": "<Replace with AWS Lambda Execution Role ARN from Alexa-hosted skill>"},
          "Action": "sts:AssumeRole"
        }
      ]
    }
    
  5. Click Update Trust Policy.

Use personal AWS resources with Node.js

In the code for your Alexa-hosted skill, assume the role by using the AWS Security Token Service (STS) API. For example, the following code requests temporary credentials of a role with AWS DynamoDB access, and scans the DynamoDB table.

Copied to clipboard.


const AWS = require("aws-sdk");

const ShowUserMessageHandler = {
    //... Your canHandle function for intent ...

    async handle(handlerInput) {
        // 1. Assume the AWS resource role using STS AssumeRole Action
        const STS = new AWS.STS({ apiVersion: '2011-06-15' });
        const credentials = await STS.assumeRole({
            RoleArn: '<Your AWS resource role ARN>',
            RoleSessionName: 'ExampleSkillRoleSession' // You can rename with any name
        }, (err, res) => {
            if (err) {
                console.log('AssumeRole FAILED: ', err);
                throw new Error('Error while assuming role');
            }
            return res;
        }).promise();

        // 2. Make a new DynamoDB instance with the assumed role credentials
        //    and scan the DynamoDB table
        const dynamoDB = new AWS.DynamoDB({
            apiVersion: '2012-08-10',
            accessKeyId: credentials.Credentials.AccessKeyId,
            secretAccessKey: credentials.Credentials.SecretAccessKey,
            sessionToken: credentials.Credentials.SessionToken
        });
        const tableData = await dynamoDB.scan({ TableName: 'TestTable' }, (err, data) => {
            if (err) {
                console.log('Scan FAILED', err);
                throw new Error('Error while scanning table');
            }
            return data;
        }).promise();

        // ... Use table data as required ...
    }
};

Use personal AWS resources with Python

In the code for your Alexa-hosted skill, assume the role by using the AWS Security Token Service (STS) API. For example, the following code requests temporary credentials of a role with AWS DynamoDB access, and then it scans the DynamoDB table.

Copied to clipboard.

import boto3

def handle(self, handler_input):
    # type: (HandlerInput) -> Response

    # 1. Assume the AWS resource role using STS AssumeRole Action
    sts_client = boto3.client('sts')
    assumed_role_object=sts_client.assume_role(RoleArn="<Your AWS resource role ARN>", RoleSessionName="AssumeRoleSession1")
    credentials=assumed_role_object['Credentials']

    # 2. Make a new DynamoDB instance with the assumed role credentials
    dynamodb = boto3.resource('dynamodb',
                      aws_access_key_id=credentials['AccessKeyId'],
                      aws_secret_access_key=credentials['SecretAccessKey'],
                      aws_session_token=credentials['SessionToken'],
                      region_name='us-east-1')

    # 3. Perform DynamoDB operations on the table
    try:
        table = dynamodb.Table('TestTable')
        response = table.scan()
        # Use the response as required . .
    except ResourceNotExistsError:
        # Exception handling
        raise
    except Exception as e:
        # Exception handling
        raise e
    # continue . .
    return (
        handler_input.response_builder.response
    )

Was this page helpful?

Last updated: Nov 23, 2023