Authentication for Alexa

As a brand new HA user, I struggled with this for a bit. As far as I can tell, there is no way to specify the bearer token needed for the LLAT in Amazon’s API.

Eventually I had to cry uncle and setup a Lambda function to add the token and forward the requests to my https endpoint: (based on the forwarding function found here)

Configure it as a nodejs 10.x script with 3 environment variables:

HA_ENDPOINT: full url of your endpoint (e.g, ‘https:///api/alexa’)
TOKEN: your long-lived access token
DEBUG: optional value for controlling logged output. 0-5, default 0

var http = require('http');
var https = require('https');
var URLParser = require('url');
 
exports.handler = function (json, context) {
    try {
        const debugLevel = process.env.DEBUG || 0;

        if (debugLevel > 0 && debugLevel < 3) console.debug('intent:', json.intent); 
        if (debugLevel > 0 && debugLevel > 2) console.debug('json request:', JSON.stringify(json) );

        const endpoint = process.env.HA_ENDPOINT;
        if (!endpoint) { context.fail('HA_ENDPOINT environment variable not configured.'); }
        
        const token = process.env.TOKEN;
        if (!token) { context.fail('TOKEN environment variable not configured.'); }

        const url = new URLParser.parse(endpoint);
        const post_data = JSON.stringify(json);
        
        // An object of options to indicate where to post to
        const post_options = {
            protocol: url.protocol,
            host: url.hostname,
            port: url.port,
            path: url.pathname,
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Content-Length': post_data.length,
                'Authorization': `Bearer ${token}`
            }
        };

        if (debugLevel > 0 && debugLevel > 2) console.debug('post options:', post_options);

        const scheme = (url.protocol === 'https:') ? https : http;
        
        // Initiate the request to the HTTP/HTTPS endpoint
        var req = scheme.request(post_options,function(res) {
            var body = "";
            // Data may be chunked
            res.on('data', function(chunk) {
                body += chunk;
            });

            debugLevel < 5 || console.debug(res);

            res.on('end', function() {
                debugLevel < 1 || console.debug('Response body:');
                debugLevel < 1 || console.debug(body);
                // When data is done, finish the request
                context.succeed(JSON.parse(body));
            });
        });
        req.on('error', function(e) {
            context.fail('problem with request: ' + e.message);
        });
        // Send the JSON data
        req.write(post_data);
        req.end();        
    } catch (e) {
        context.fail("Exception: " + e);
    }
};