5

I'm currently struggling with integrating Amazon Alexa with our current systems. The TL;DR version of what I have to do is that I should be able to create an Alexa skill programatically via the Alexa Skill Management API.

While this is pretty straightforward, I've hit a roadblock with the authentication phase (which involves Login With Amazon):

The way this was supposed to work is that each request you make against the SMAPI endpoints must contain the authorization token in the Authorization HTTP header.

Let's say I make a POST request to https://api.amazonalexa.com/v0/skills with this body:

{
"vendorId":"my-vendor-id",
"skillManifest": {
    "publishingInformation": {
        "locales": {
            "en-US": {
                "summary": "This is a sample Alexa skill.",
                "examplePhrases": [
                    "Alexa, open sample skill.",
                    "Alexa, turn on kitchen lights.",
                    "Alexa, blink kitchen lights."
                ],
                "keywords": [
                    "Smart Home",
                    "Lights",
                    "Smart Devices"
                ],
                "name": "Sample custom skill name.",
                "description": "This skill has basic and advanced smart devices control features."
            }
        },
        "isAvailableWorldwide": false,
        "testingInstructions": "1) Say 'Alexa, discover my devices' 2) Say 'Alexa, turn on sample lights'",
        "category": "SMART_HOME",
        "distributionCountries": [
            "US",
            "GB"
        ]
    },
    "apis": {
        "custom": {
            "endpoint": {
                "uri": <some-aws-lambda-endpoint-uri>"
            }
        }
    },
    "manifestVersion": "1.0",
    "privacyAndCompliance": {
        "allowsPurchases": false,
        "locales": {
            "en-US": {
                "termsOfUseUrl": "http://www.termsofuse.sampleskill.com",
                "privacyPolicyUrl": "http://www.myprivacypolicy.sampleskill.com"
            }
        },
        "isExportCompliant": true,
        "isChildDirected": false,
        "usesPersonalInfo": false
    }
  }
}

And these header fields:

{
"Authorization":"<my-auth-token-that-i-get-from-lwa>"
}

The expected response should be in this format:

{
  "skill_id": "{skill_id}"
}

However, this is the response that I get:

{
  "message": "User has not consented to this operation"
}

(This is despite the fact that the user in question has already consented to these operations, which is quite evident with this permission request array:

['profile profile:user_id alexa::ask:skills:readwrite alexa::ask:skills:test alexa::ask:models:readwrite alexa::ask:skills:test alexa::ask:models:read alexa::ask:skills:read']

)

Additionally, if I add the Bearer prefix to the Authorization header this way:

{
    "Authorization":"Bearer <my-lwa-auth-token>"
}

I get this response:

{
    "message": "Token is invalid/expired"
}

Which is quite surprising considering the fact that the auth token was generated only ten (maybe fifteen) minutes ago, and that it is still within it's shelf life (which is about an hour).

In another thread here, I head read that Amazon are working on this issue (that was October 21, 2017). In the mean time, if you've worked out another method, could you please describe it and help a fellow out?

  • Also facing the same issue. Got any results on that? One strange thing is that I can make a GET request with that same token without any problems. But when trying to post a skill, I get the same error message back: "message": "Token is invalid/expired" Any ideas/solutions? – bobski Jun 30 '18 at 16:24
  • No, @LucaKiedrowski . I had given up on this exercise the next week. Wasn't turning out to be worth my time. – Prashant Warrier Jul 08 '18 at 12:19
  • I solved the problem. In what language are you writing this? I made that request with a module, then tried to do it manually and somehow that worked. – bobski Jul 08 '18 at 12:52
  • That was with JavaScript (Node.JS) – Prashant Warrier Jul 09 '18 at 08:45
  • Hitting the same problem using Python (using requests), @LucaKiedrowski, what module did you use? What changed when this got solved? – Josep Valls Oct 02 '18 at 20:29

1 Answers1

0

The easiest way to hit SMAPI from Node is to use the SMAPI Node.js SDK, with docs available here.

In order to authenticate with SMAPI, you're going to need to do the following:

  1. Set up an LWA security profile.
  2. Use the ASK CLI to exchange your LWA Client ID and Client Secret for an LWA refresh token using ask util generate-lwa-tokens --client-id <Client ID> --client-confirmation <Client Secret>.
  3. Use this refresh token when you initialize the SMAPI node SDK:
const Alexa = require('ask-smapi-sdk');

// specify the refreshTokenConfig with clientId, clientSecret and refreshToken generated in the previous step
const refreshTokenConfig = {
    clientId,
    clientSecret, 
    refreshToken
}
const smapiClient = new Alexa.StandardSmapiClientBuilder()
    .withRefreshTokenConfig(refreshTokenConfig)
    .client();

You will then be able to hit SMAPI through function calls on the SDK!

Helpful resource on this: https://levelup.gitconnected.com/email-yourself-daily-alexa-skill-metrics-updates-using-lambda-smapi-and-ses-9c16ac97c1f8

smapi_guru
  • 51
  • 1