DPH.AM

I like to draw, code, and build stuff.

API Authentication Inside an Amazon Echo App

I recently participated in a brainstorm session to generate ideas for an internal Echo hackathon and noticed a lot of ideas required hitting an external API to retrieve data to respond back to the user. The power of the Echo is simply taking a user’s voice input and transforming it into intents and deferring the processing to an external service. Sure, there were a few ideas that were self-contained (I think Echo karaoke was the most compelling one), but I think the majority of Echo apps will be a voice proxy to an external API. I spent very little time going through the API docs and haven’t built a full-blown Echo app, so take this with a grain of salt. I’ve noticed two common problems developers will find frustrating; hitting a local internet of things (IoT) service and authenticating an API request.

Echo apps are just HTTPS endpoints. When you send a launch command to your Echo, the Alexa service finds the URL associated with the app and performs a POST request. Therefore your web service must be publicly accessible which makes it difficult to communicate with IoT services connected to your local network. I have some ideas around this (and I think Amazon does as well since the Amazon Echo companion app can detect Hue lights in your network), but I’ll defer to a different blog post.

Some API calls such as getting weather information, stock prices, and horoscopes are generic and doesn’t require any authentication. However, Alexa would be a very useless companion if she only gave you generic information. Imagine being able to say “Alexa, open Uber and find me a ride” as you’re putting on your jacket in the morning, and the Echo app uses your Uber account to request a ride and direct the driver to your apartment (this was my team’s Echo hackathon idea). Or during a gathering with friends, be able to say “Alexa, open Drizly and order me a pack of my favorite IPA” (this is actually my current pet project).

The Problem

The problem I ran into was associating my account for this external service with my Amazon/Echo account. Inputs for Echo apps are voice-only, and although I’ve never built an experience to enter user name and password via speech, I have a feeling it’s not a viable option. Sure, as a hack for personal use, I could generate my auth token separately and hardcode it into my app, but I wanted to share this app with friends so hardcoding the token wasn’t gonna cut it.

The Ideal Solution

Here’s a screenshot of the Echo companion app listing installed apps; in this case I have one app installed called fridge.

"Installed Echo App"

When tapping on the app, there’s only one option which is to uninstall. Ideally the Echo API should have a way for apps to provide a webview which can be opened from the companion app/website. This is the perfect place for developers to implement authorization.

Notice however, there are a few non-Amazon apps in the menu such as Pandora, iHeartRadio, and TuneIn. It appears this is built directly into the Echo app and is the exact place that could hold a more seamless auth experience. Here’s a screenshot of the companion app after I tapped on Pandora.

"Echo Pandora App"

My Current Solution

1) Get the user’s auth token to hit these 3rd party APIs

Build a webpage where users can log in with their 3rd-party credentials. Obviously this step is only require for third party developers. Use this information to generate an auth token (assuming that API has a sane implementation) and store it in your database. After you get the user’s auth token…

2) Associate auth token with user’s Echo/Amazon account

Every Amazon account has an assigned user_id that uniquely identifies the user’s account. This information is attached to every request to your app from Echo.

Here’s an example of the request body from an Echo hitting your app.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
  "version": "1.0",
  "session": {
      "new": false,
      "sessionId": "amzn1.echo-api.session.abc-123",
      "user": { "userId": "amzn1.account.K2LI23KL2LK2" },
      "attributes": {
          "string": {}
      }
  },
  "request":  {
      "type": "IntentRequest",
      "requestId": "amzn1.echo-api.request.abc-123",
      "intent": {
          "name": "MyIntent",
          "slots": {
              "SlotName": {
                  "name": "SlotName",
                  "value": "string"
              }
          }
      }
  }
}

You also get the user_id in the customer profile data when using Login with Amazon

1
2
3
4
5
{
  "email": "johndoe@gmail.com",
  "name": "John Doe",
  "user_id": "amzn1.account.K2LI23KL2LK2"
}

Once you associate the auth token with an Amazon customer’s user_id using Login with Amazon, simply use the userId key from an Echo request to retrieve the token (and any other information about the user that you might have stored).

This solution requires users to manually authenticate through your website. It’s certainly not ideal, but they only have to do it once (or until auth token expires).

Comments