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.
When using Authorization Code grant, Token URL is expected to have following format.
*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
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..."
}
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.
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.
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;
};
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.
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.
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.
Now Link POST request to Lambda function we created for TokenAPI.
Once the POST method is added to API, you will see following 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.
{"queryParam1":"$input.params('queryParam1')","payload":$input.json('$')}
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.
Now deploy this API to production so as to generate a HTTPS URL for external use.
As shown above a url https://xxxxxxxxxxx.execute-api.eu-west-1.amazonaws.com/Production is generated for external use.
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.
Now modify the skill you were troubleshooting for Account Linking setup and use our newly created TokenAPI.
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.
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.
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.