What is the setup for Alexa Custom Skill w/ 0.77 Auth System?

The issue is that, once you’ve linked the account in the Alexa skill, the OAuth credentials are passed in the body of the request from the Alexa skill rather than as an Authorization: Bearer header. To get it working again you can set up an AWS Lambda function to point the Alexa skill to, similar to the setup for the Smart Home integration. Basically follow the instructions for setting up the Lambda function for the Alexa Smart Home integration, but use something like the following for your lambda function code:

# -*- coding: utf-8 -*-
import os
import json
import logging
import urllib3

_debug = bool(os.environ.get('DEBUG'))

_logger = logging.getLogger('HomeAssistant-Intents')
_logger.setLevel(logging.DEBUG if _debug else logging.INFO)


def lambda_handler(event, context):
    """Handle incoming Alexa directive."""

    _logger.debug('Event: %s', event)

    base_url = os.environ.get('BASE_URL')
    assert base_url is not None, 'Please set BASE_URL environment variable'

    try:
        token = event.get('session', {}).get('user', {}).get('accessToken')
    except AttributeError:
        token = None

    if token is None and _debug:
        token = os.environ.get('LONG_LIVED_ACCESS_TOKEN')

    assert token, 'Could not get access token'

    verify_ssl = not bool(os.environ.get('NOT_VERIFY_SSL'))

    http = urllib3.PoolManager(
        cert_reqs='CERT_REQUIRED' if verify_ssl else 'CERT_NONE',
        timeout=urllib3.Timeout(connect=2.0, read=10.0)
    )

    response = http.request(
        'POST',
        '{}/api/alexa'.format(base_url),
        headers={
            'Authorization': 'Bearer {}'.format(token),
            'Content-Type': 'application/json',
        },
        body=json.dumps(event).encode('utf-8'),
    )
    if response.status >= 400:
        return {
            'event': {
                'payload': {
                    'type': 'INVALID_AUTHORIZATION_CREDENTIAL'
                    if response.status in (401, 403) else 'INTERNAL_ERROR',
                    'message': response.data.decode("utf-8"),
                }
            }
        }
    
    return json.loads(response.data.decode('utf-8'))
2 Likes

@lpomfrey thank you for taking the time to find and then reply to this thread with the answer you’ve provided. Your explanation makes sense and can see the difference in your altered Lambda function.

I’ve quickly added a new Lambda function and used the “Alexa Skills Kit” instead of “Smart Home” and have went back into my custom intents test skill to update the endpoint from HTTPS to AWS Lambda.

The account has been linked via the Alexa app and I’ve quickly configured the skill with some intents but something isn’t working as I keep getting “there was a problem with the requested skills response”. I’ve run out of time to test it further this morning as I need to go through everything and double check.

Just wanted to post a quick update as a sign of appreicatation for your input hopefully between us and anyone else who wants to try setting this up we can finally get custom intents working utilsing the updated authentication system! :+1:

I shall keep everyone updated with my progress.

That might be because the editor seemed to have messed up the indentation of my code sample, in particular by indenting the last line. I’ve edited it to fix that.

If you can get it working so I’m sure it’s not only working for me I’ll try to find the time to submit a pull request to Home Assistant updating the documentation.

@lpomfrey you’re an absolute champion, it works! I couldn’t help myself after seeing your last reply. A pull request to the HA documentation sounds like a solid plan!

@TarheelGrad1998, @tuncaya, @ahknight - a solution has been found at last lads!

P.S. Also, welcome to the forums @lpomfrey :wave:.

Thanks, I’ll try it. I’m glad there’s a workaround, but wish we didn’t have to use AWS in the first place.

Why doesn’t Home Assistant send the authentication to Amazon right in the first place?

It’s not so much that Home Assistant doesn’t send the authentication right, but that Amazon sends it back in a way that Home Assistant doesn’t understand. Once your Alexa app has an authentication token (from the account-linking process) it sends it within the body of the request it makes back to Home Assistant, whereas Home Assistant expects it to be sent as an Authorization header. All the AWS Lambda functions do (for intents and the smart home integration) is grab the authentication token from the request body, put it in the header Home Assistant expects, and forward the original request plus the header to Home Assistant.

You don’t necessarily need to use AWS, there are a few ways around it. You could write a simple API endpoint in appdaemon, or a little Python HTTP server app, or even use the Nginx Lua processing module to do the same thing.

Great glad it works for you too. I’ll try and get a pull request together soon.

Finally getting back to this. Briefly flirted with rolling my own to avoid AWS, but gave up. At least the AWS limit is more than sufficient, and I’m already indebted to Amazon plenty, so what’s another hook? :slight_smile:

Anyway, worked great for me also. Got my existing skill moved over also, disabled the api password, and it’s all still working! Yay for improved security with the same flexibility.

Thanks again, @lpomfrey

I’m very new to this, so I apologize for any dumb questions.
I added this code to AWS and set up my skill endpoint. I am able to link the account, but the function doesn’t seem to be working.
When I try to query my custom intents, I just get an error that their was a problem with the requested response.
I have set the BASE_URL and DEBUG environment variables, but I don’t get any log messages in cloudwatch or on the alexa console site. Can anyone give me an idea what might be going on here or how to debug this?
I do see log events being generated in Cloudwatch, so the function is attempting to run. The only messages I see though are “start request” and “end request” events.

Without knowing more about how exactly you’ve set everything up, I would suggest checking the following:

  • You are using the “Alexa Skills Kit” trigger integration rather than the “Alexa Smart Home” trigger in your Lambda function and have copied in the correct Alexa Skill ID (Should look something like amzn1.ask.skill.01234567-0123-4567-89a-0123456789ab to the config there.
  • You don’t have a trailing slash in your BASE_URL variable.
  • Your Home Assistant instance is definitely accessible externally and via HTTPS (or you’ve set the NOT_VERIFY_SSL environment variable to 1.
  • Your intent and slot names match between Home Assistant and the Alexa skill.
  • You’ve correctly copied the Lambda ARN (should look something like arn:aws:lambda:aws-location:0123456789ab:function:homeassistant_intents) into the skill endpoint and selected AWS Lambda ARN for the endpoint type on the Alexa Skill.

Hi there,
I am bit desperate, I change my Alexa custom skill to use a lambda function as endpoint and make the linkage in between my Amazon and Home Assistant Accounts. In the Alexa app when I make the account linkage it prompts the Home Asistant user and password request. Afther that, I am able to enter my HA user and password, and after a few seconds I always get the same error message, it has not been posible to link Home Assistant at this moment. I have reviewed the skill and lambda set-up. code and parameters a billion times. Any idea ? I am in EU using Ireland.

I finally managed to get it work. The fix consist on using the port 443 rather tan 8123 in the lambda and skill account linkage definition.

I’ve recently moved to the new auth system. Most of the time (~70%) my skills work properly. Sometimes, though, I get the “There was a problem with the selected skill’s response” message.

The skill works - the automation actions take place - but the reply text isn’t spoken. Just the error.

Any thoughts? I’ve tried bumping up the timeouts, but that had no effect.

same problem here, when i test my alexa skill I always get:

There was a problem with the requested skills response

my skill configuration is:

Endpoint

    Service Endpoint Type: HTTPS
    Default Region: https://myname.duckdns.org:8123/api/alexa

Account Linking

    Do you allow users to create an account or link to an existing account with you? = ON
    Allow users to enable skill without account linking (Recommended). = OFF
    Security Provider Information = Auth Code Grant
    Authorization URI*: https://myname.duckdns.org:8123/auth/authorize
    Access Token URI: https://myname.duckdns.org:8123/auth/token
    Client ID*: https://layla.amazon.com/ (i'm in italy)
    Client Secret*: bla bla bla
    Client Authentication Scheme*: Credentials in request body
    Scope: intent
    Domain List: blank
    Default Access Token Expiration Time: blank

i didn’t understand if i have to include :8123 in the url or not… anyway, also without doesn’t work! In my firewall I had created a nat rule to forward outside 443 to internal 8123 port

here the json:

{
	"version": "1.0",
	"session": {
		"new": true,
		"sessionId": "amzn1.echo-api.session.123-123-123-123-123",
		"application": {
			"applicationId": "amzn1.ask.skill.123-123-123-123-123"
		},
		"user": {
			"userId": "amzn1.ask.account.123123123"
		}
	},
	"context": {
		"System": {
			"application": {
				"applicationId": "amzn1.ask.skill.123-123-123-123-123"
			},
			"user": {
				"userId": "amzn1.ask.account.123123123"
			},
			"device": {
				"deviceId": "amzn1.ask.device.123123123",
				"supportedInterfaces": {}
			},
			"apiEndpoint": "https://api.eu.amazonalexa.com",
			"apiAccessToken": "123123123"
		},
		"Viewport": {
			"experiences": [
				{
					"arcMinuteWidth": 246,
					"arcMinuteHeight": 144,
					"canRotate": false,
					"canResize": false
				}
			],
			"shape": "RECTANGLE",
			"pixelWidth": 1024,
			"pixelHeight": 600,
			"dpi": 160,
			"currentPixelWidth": 1024,
			"currentPixelHeight": 600,
			"touch": [
				"SINGLE"
			],
			"video": {
				"codecs": [
					"H_264_42",
					"H_264_41"
				]
			}
		},
		"Viewports": [
			{
				"type": "APL",
				"id": "main",
				"shape": "RECTANGLE",
				"dpi": 160,
				"presentationType": "STANDARD",
				"canRotate": false,
				"configuration": {
					"current": {
						"video": {
							"codecs": [
								"H_264_42",
								"H_264_41"
							]
						},
						"size": {
							"type": "DISCRETE",
							"pixelWidth": 1024,
							"pixelHeight": 600
						}
					}
				}
			}
		]
	},
	"request": {
		"type": "IntentRequest",
		"requestId": "amzn1.echo-api.request.123-123-123-123-123",
		"timestamp": "2020-02-05T12:40:29Z",
		"locale": "it-IT",
		"intent": {
			"name": "UmiditaCameraIntent",
			"confirmationStatus": "NONE"
		}
	}
}

problem solved! My error! I was testing with the amazon web without adding the skill to alexa and authentication to my ha!