Editor's Note: This post was updated in January 2019.
Some skills require the ability to connect the identity of an Alexa end user with a user in another system, such as Twitter, Facebook, Amazon, and many others. For example, suppose you own a web-based service “Car-Fu” that lets users order taxis. It would be very convenient for people to access Car-Fu by voice (“Alexa, ask Car-Fu to order a taxi”).
To accomplish that, you’d use a process called account linking, which provides a secure way for Alexa skills to connect with third-party systems requiring authentication.
Skills that use the Smart Home Skill API must use account linking (with the authorization code grant flow) to connect the Alexa user with their device cloud account. Custom skills can use account linking if desired. However, if your custom skill merely needs to keep track of a user to save attributes between sessions, you do not need to use account linking.
There are many ways you can use account linking to enhance your Alexa skills. For example:
Account linking leverages OAuth 2.0; an open protocol that provides a simple, standards-based method for web, mobile and desktop applications to request user authorization from remote servers.
As a skill developer, you could set up and configure your own OAuth server and identity management system. At some large companies, an OAuth server is probably already available and Identity Management procedures already in place. However, at smaller companies, this would require you to build, operate, and maintain your own complex system to manage user identities, passwords, and profiles in a secure and scalable way.
Many organizations rely instead on well-known identity providers, available on the internet. These are sites where nearly everyone has an account, such as Facebook, Google, Twitter, and Amazon. The service that acts as a public-facing identity provider for Amazon is Login with Amazon.
When using OAuth, you delegate user authentication to a third-party Identity Provider (IDP). As illustrated below, the user is redirected to the IDP web site. User authentication happens according to the IDP’s policies (username and password, one-time password, biometric, etc.), and upon successful authentication, the IDP generates an implicit grant (aka bearer token) or an authorization code grant.
The bearer token is the token you'll use for accessing information and services. On the other hand, an authorization code can only be used to request a bearer token. This usually happens on the backend, between your application server and the IDP service. While an implicit grant is often faster and simpler for developers to request, an authorization code grant is generally considered more secure and some IDPs may require it for sensitive information or services. Also, a code grant allows for automatic refreshing of the bearer token after a given expiry, which will be set according to the IDP’s policy. When using an implicit grant, the user has to manually re-authenticate themselves when attempting to use the service, which, depending on the lifespan of the bearer token, can cause friction for account linking in applications.
After authentication is complete and a valid token is received, your application is responsible for managing authorization based on the customer's profile.
Follow these steps to configure your Alexa skills with account linking and Login with Amazon.
If you haven’t created a skill yet, please first use the Alexa Skills Kit to build something relatively simple, such as a trivia skill. You can get a prototype up and running in just a few hours and come back here once it’s published.
First, you need to create a LWA profile for your Alexa skill. Here’s how.
Fill in all three required fields to create your security profile and click “Save.” For the purpose of this article, I am using Amazon’s privacy policy URL. Make sure to replace the link with a link to your own Data Privacy policy. The end result should look like this:
Before you complete this step, be sure to copy your Client ID and Client Secret from the Web Settings tab (see Figure 4) to a text editor so they're easily available. You’ll need these values later in the process.
Now that you’ve configured Login with Amazon, you can configure Account Linking for your Alexa skill. (Remember, you need to have a skill already created to do this). In the Alexa developer console, choose the skill you want to edit (or create a new skill).
Under the “Build” tab for your skill, click “Account Linking” on the left side. To enable account linking, turn on the “Do you allow users to create an account or link to an existing account with you?” toggle.
Choose “Allow users to enable skill without account linking” if you want to allow users to start to use the skill without Account Linking and let them link their account later during the skill usage (see Optional Account Linking for the details).
Then, enter the following:
The values you need to enter into these fields are detailed in the table below.
Key |
Value |
Authorization Grant Type |
Auth Code Grant |
Authorization URI |
https://www.amazon.com/ap/oa |
Access Token URI |
https://api.amazon.com/auth/o2/token |
Client ID |
The Client ID received from Login with Amazon during Step 1 above. This has a format such as amzn1-application-oa2-client-xxx |
Client Secret |
The client secret received from Login With Amazon during Step 1 above. |
Scope |
Login with Amazon supports several scopes, for this example, let’s use “profile”. This will allow your code to retrieve a unique Amazon userid, email address, and full name for the user. |
The last step is to configure Login with Amazon to accept our redirection URLs. The redirection URLs are given on the Alexa Developer Console, 1 per geographic area, under “Redirect URL”. These are the URLs starting by https://pitangui.amazon.com/… (North America) or https://layla.amazon.com/... (EU and India) https://alexa.amazon.co.jp... (Far East)
Copy this value to that text editor I suggested earlier and go back to the Login with Amazon console.
Next to the Security Profile you created in Step 1, click the button with the gear icon and select “Web Settings” from the menu.
Click the "Edit" button in the lower right, then enter the Redirect URL, as it appears on the ASK Developer Console.
Now you are ready to write some code.
For the purpose of this blog post, I chose to write the Alexa custom skill code in NodeJS and deploy it on AWS Lambda.
You can learn more about writing code for custom skills here.
When your skill is called the first time, you will receive a JSON document like this:
{
"session": {
"sessionId": "SessionId.7c77f955-ae5e-46f1-a9ca-3fb354b1ce77",
"application": {
"applicationId": "amzn1.echo-sdk-ams.app.fb2fc3e7-55e7-4f05-851e-7ad308a6b499"
},
"user": {
"userId": "amzn1.ask.account.AFP3ZWPOS2BGJR7OWJZ3DHPKMOMNWY4AY66FUR7ILBWANIHQN73QHMAHCTVTAHFPUV3WAFNGKBYW5LFUE2WV4CCGEISSPHBHCW5SCYJDL3DLWRRRBB4CQIP3X3PV65V2AYMMXSNFPKHPZJFVAH5AHKHDLAER67H3AHL4XBUU76XEH5BGDZZNGV5T6HHAGN6KGZI777J3VA7WGPA"
},
"new": true
},
"request": {
"type": "IntentRequest",
"requestId": "EdwRequestId.b595d667-caa3-4818-8d4a-c7a31e8adddc",
"timestamp": "2016-05-27T15:36:26Z",
"intent": {
"name": "SayHello",
"slots": {}
},
"locale": "en-US"
},
"version": "1.0"
}
Notice that the “user” section contains a userId properties, but no OAuth access token is available yet as we did not authenticate our user yet.
Whenever users invoke intents in your skill that rely on information obtained from account linking, your skill code should return a “LinkAccount” card to be displayed in the Alexa app or the Alexa web site. In this example, the card will contain a link allowing the user to authenticate on Login with Amazon. In addition to the card, it is a recommended practice to return a voice prompt inviting the user to authenticate in the app.
Below is an example of what this might look like using the ASK SDK for Node.js V2:
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent';
},
async handle(handlerInput) {
const { accessToken } = handlerInput.requestEnvelope.context.System.user;
let speechText = '';
if (!accessToken) {
speechText = 'You must authenticate with your Amazon Account to use this skill. I sent instructions for how to do this in your Alexa App';
return handlerInput.responseBuilder
.speak(speechText)
.withLinkAccountCard()
.getResponse();
} else {
speechText = 'Hello World!';
return handlerInput.responseBuilder
.speak(speechText)
.getResponse();
}
}
}
And the corresponding JSON output looks like this:
{
"version": "1.0",
"response": {
"outputSpeech": {
"type": "PlainText",
"text": "You must authenticate with your Amazon Account to use this skill. I sent instructions for how to do this in your Alexa App"
},
"card": {
"type": "LinkAccount"
},
"shouldEndSession": true
},
"sessionAttributes": {}
}
When you invoke your skill from a device, you will receive a card in the Alexa app asking you to link your account.
Click on the “Link Account” link, and the Login with Amazon page will display.
Authenticate using your regular Amazon login (the same login used when shopping on Amazon.com).
The very first time, Amazon will ask you if you authorize the Alexa skill to retrieve some data from your user profile.
Click ‘Okay’ and a confirmation message appears.
Invoke the skill again. Now, because your account is linked, an Amazon OAuth Token is included in the input JSON document.
{
"session": {
"sessionId": "SessionId.7fc6aa11-8a2c-4f3f-a1ea-001569cd0035",
"application": {
"applicationId": "amzn1.echo-sdk-ams.app.fb2fc3e7-55e7-4f05-851e-7ad308a6b499"
},
"user": {
"userId": "amzn1.ask.account.AFP3ZWPOS2BGJR7OWJZ3DHPKMOMNWY4AY66FUR7ILBWANIHQN73QHMAHCTVTAHFPUV3WAFNGKBYW5LFUE2WV4CCGEISSPHBHCW5SCYJDL3DLWRRRBB4CQIP3X3PV65V2AYMMXSNFPKHPZJFVAH5AHKHDLAER67H3AHL4XBUU76XEH5BGDZZNGV5T6HHAGN6KGZI777J3VA7WGPA",
"accessToken": "Atza|IQEBLjAsAhRBk1-yYVTk9HhZEQnTGL9F3RHS5gIUG0rrerkVvpVTF5kIFWBvZIx7QtJCkzsRFRf1ZAIZeRz6FJwdeyQCLPEbqLnEKU-zQF4n9x76Dl24Rt7HiltefBilnDm0c2PZQP_IUBAzcm93CIDxsMYhEmW_Pr0Tm9tIrGzNzVntLgyiUeXmasL1bUOIv_om66ZVwd7urpyiJSoSbA-1NQ7O9AKC2qXMqvFpvFUBSvgCYoTyyAkOePN63FCaq9NJPYbJLuocqcuyGz9mygNqp9_mNRWRRzcoeSTxpUoa8LxW-IvVVFEA1omCfXmcVijEZA6nbi-EzheMG7fu1y0XNGPEy40Csq7H07wrSqksz9IDIUd4tmqiYsJpN4dxfoGddEauC3i4eLCvsg8gbu963CqqUQ3COxgrWKTsqX8AsT8FCFvmfW3IYfhCG6KuPw8qntBgAU-W9pW523lERQKLxzI07UHyMd2R-Fnaw8IWbBYFCbblwIJhf6twjz9z_4h320f4ywczBa3k_LCoE0VpidER7rVgBtfreox-XYqV5jw"
},
"new": true
},
"request": {
"type": "IntentRequest",
"requestId": "EdwRequestId.31777921-9438-44f7-b271-6b9808d5fba9",
"timestamp": "2016-05-27T16:18:57Z",
"intent": {
"name": "SayHello",
"slots": {}
},
"locale": "en-US"
},
"version": "1.0"
}
Your code can use this access token to fetch the user profile data from the Amazon Profile service API. Here is an asynchronous function to retrieve the Amazon profile. This function uses the Axios request library, which you can add by typing “npm install axios” in your project’s root directory. You can then import it at the top of your index.js file.
const axios = require('axios');
And then in your handle function (notice the async and await keywords):
const HelloWorldIntentHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === 'IntentRequest'
&& handlerInput.requestEnvelope.request.intent.name === 'HelloWorldIntent';
},
async handle(handlerInput) {
const { accessToken } = handlerInput.requestEnvelope.context.System.user;
let speechText = '';
if (!accessToken) {
speechText = 'You must authenticate with your Amazon Account to use this skill. I sent instructions in how to do this in your Alexa App';
return handlerInput.responseBuilder
.speak(speechText)
.withLinkAccountCard()
.getResponse();
} else {
const amznProfileUrl = `https://api.amazon.com/user/profile?access_token=${accessToken}`;
try {
const response = await axios.get(amznProfileUrl);
speechText = `Hello, ${response.data.name.split(" ")[0]}!`;
} catch (error) {
console.error(error);
speechText = 'Hello!';
}
return handlerInput.responseBuilder
.speak(speechText)
.getResponse();
}
}
}
The code above will return the following JSON output:
{
"version": "1.0",
"response": {
"outputSpeech": {
"type": "PlainText",
"text": "Hello, Sebastien"
},
"shouldEndSession": true
},
"sessionAttributes": {}
}
Congratulations, if you coded along to this point, you have successfully implemented Account Linking with the Login with Amazon service.
Tell us how you’re enhancing your Alexa skills using account linking by tweeting us @AlexaDevs. For further info, check out our developer pages on Account Linking and how to use the Login with Amazon service.