Alexa Account Linking : Debugging OAuth Token URL using API wrapper

Sumit Marwal Aug 17, 2020
Share:
Tips & Tools
Blog_Header_Post_Img

When creating a Custom skill, Smart Home or Video Skill that requires Account linking, developers occasionally face errors that are difficult to troubleshoot, primarily because of lack of logs or any additional debug information. OAuth configuration for skills is based on 1) OAuth Login page and 2) OAuth Token URL. In this blog we are going to talk about debugging token URL issues.

Solving issues with a Token URL can be frustrating because there is very little information available for debugging. Token URL implementation might fail because of “incorrect SSL certificate”, “IP restrictions”, “incorrect API response encoding” or many other possiblities.

In this blog, we are going to follow an approach of using a Dummy OAuth Token URL and then gradually use it for debugging and solving the actual Token URL in use.

Please note, that all the examples used in this blog are purely for debugging url issues and you SHOULD NOT use Lambda or API gateway as a wrapper on a token URL for production skills.

Token URL Specification

When using Authorization Code grant, Token URL is expected to have following format.

Request Format

Copied to clipboard
*POST* /auth/o2/token HTTP/1.1
Host: api.amazon.com
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
 
grant_type=authorization_code
&code=123456EXAMPLE
&client_id=exampleId
&client_secret=ABCDEFGEXAMPLE

Response Format

Copied to clipboard
HTTP/1.1 200 OK
Content-Type: application/json;charset UTF-8
*Cache*-Control: *no*-*store*
*Pragma*: *no*-*cache*
{
   "access_token":"Atza|EXAMPLEACCESSTOKEN123456...",
   "token_type":"bearer",
   "expires_in":3600,
   "refresh_token":"Atzr|EXAMPLEREFRESHTOKEN123456X..."
}

Creating a Dummy Token URL using AWS Lambda and API Gateway

As a first step in debugging account linking Token URL issue, let’s create a Dummy Token URL that always returns success response. We will use AWS API Gateway and a Lambda to create a Dummy URL.

Step 1: Create Lambda for API Gateway

Create an Empty Lambda function with basic execution role. Let’s name it “tokenURLLambda” in our example. Use Virginia or Ireland endpoint as it will allow us to debug any geo-restriction that are placed on production token URL by your local IT team.

We will add following hard-coded response to this Lambda to return a success for any request body.

Copied to clipboard
exports.handler = async (event) => {
    console.log(JSON.stringify(event));
    // TODO implement
    const response = {
       "access_token":"Atza|EXAMPLEACCESSTOKEN123456",
       "token_type":"bearer",
       "expires_in":3600,
       "refresh_token":"Atzr|EXAMPLEREFRESHTOKEN123456X"
    };
    return response;
};

Step 2: Create Token API

Login to AWS Console and Navigate to “API Gateway“. Choose ”Create API“ and in the list of options presented for API template, select ”REST API“ as shown in image below.

Create API

After you click on Build, you will be presented with a next screen to choose the name for API. Lets use “TokenAPI” as a name for our newly created API.

Token API

Once the API has been created, we will add a POST method to this API. Token URLs in OAuth use url-encoded format in POST request.

Create API
Post method

Now Link POST request to Lambda function we created for TokenAPI.

Link Lambda

Once the POST method is added to API, you will see following configurations.

API Configurations

Click on “Integration Request” and scroll to the bottom to see options for “Mapping Template“. Choose ”When there are no templates defined (recommended) “ and add a mapping template for Content-Type ”application/x-www-form-urlencoded“. Paste following code snippet to this mapping template.

Copied to clipboard
{"queryParam1":"$input.params('queryParam1')","payload":$input.json('$')}
Mapping Template

Save the template and go back to POST method properties. This time Select “Integration Response“ and go to ”Method Response“ settings. Modify response body to ”text/html“ format.

Response Headers

Now deploy this API to production so as to generate a HTTPS URL for external use.

Deploy
API URL

As shown above a url https://xxxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/Production is generated for external use.

Step 3: Test the Sample API in a rest client and a custom skill.

Next step is to test this API in a rest client and make sure that we get the desired response as per Token URL Specification.

Step 4: Use TokenAPI in an Alexa Skill

Now modify the skill you were troubleshooting for Account Linking setup and use our newly created TokenAPI.

Account linking

If account linking was failing due to Token URL issues then you would see that Account Linking is working now after using Dummy URL. This is because we are sending hardcoded expected response from our lambda. Next step is to debug the problem in the real Token URL and notice why is it failing.

Step 5: Configure TokenAPI to act as a Wrapper for real url.

Let’s update our lambda function with following code. This code acts as a wrapper on top of your actual token URL. Most probably you would see that your account linking again starts failing after you use Lambda as a wrapper for your token url. However this time when it fails, you would be able to see all the errors and exceptions in Lambda’s cloudwatch logs. You can also add additional logs to add any additional debugging that you want.

Copied to clipboard
var querystring = require('querystring'); //<--- MAKE SURE YOU HAVE ALL THE NODE DEPENDENCIES INSTALLED
var https = require('https');
var fs = require('fs');


exports.handler = (event, context, callback) => {
    console.log("Request - " + JSON.stringify(event));   
    // An object of options to indicate where to post to
    console.log(event.payload);
    var post_options = {
        host: 'tokenurl.com', //<--- PUT YOUR TOKEN URL DOMAIN HERE
        port: '443',
        path: '/token/Token', //<--- PUT YOUR TOKEN URL PATH HERE
        method: 'POST',
        rejectUnauthorized: false,
        headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': Buffer.byteLength(event.payload)
        }
    };
  console.log('Making request: ' + post_options);
  // Set up the request
  var post_req = https.request(post_options, function(res) {
      res.setEncoding('utf8');
      res.on('data', function (chunk) {
          console.log('Response: ' + chunk);
          callback(null, JSON.parse(chunk));
      });
      
  });
  // post the data
  post_req.write(event.payload);
  post_req.end();    
};

Note : - Make sure you install additional dependency required in this lambda code.

Once you find out the problem in token URL configuration and fix it, remember to remove the API gateway wrapper and use your actual token URL in the skill. The methods mentioned here are for debugging purposes only and NOT to be replicated in Production environment.

In this blog we showed one of the possible approach to debug Account Linking issues with Token URL by using readily available services in AWS. The advantage of using AWS API Gateway and Lambda for debugging is that it allows you to extract required logs and exceptions without touching the configurations or log level on OAuth server. 

Related Articles

Alexa Account Linking: 5 Steps to Seamlessly Link Your Alexa Skill to User Systems That Require Authentication

Related articles only have an image (the squarer version of the banner) and a title. This text can be deleted. Place 1-3 related articles.

Subscribe