Alexa proactive mode - unable to link alexa

i’m having an issue with alexa smart_home.
when i follow (https://www.home-assistant.io/components/alexa.smart_home/)
I’m able to link alexa, however if i enable Alexa’s proactive mode by adding the client_id and client_secret and then unlink and attempt to re-link. The linking fails with unable to link at this time.

alexa:
  smart_home:
    endpoint: !secret alexa_event_endpoint
    client_id: !secret alexa_client_id
    client_secret: !secret alexa_client_secret

I have noticed the following in the log file, but i think this is because it not linked.

2019-06-25 23:10:55 DEBUG (MainThread) [homeassistant.components.alexa.state_report] Received (401): {"header":{"namespace":"System","name":"Exception","messageId":"HIDDEN"},"payload":{"code":"INVALID_ACCESS_TOKEN_EXCEPTION","description":"Access token is not valid."}}
2019-06-25 23:10:55 ERROR (MainThread) [homeassistant.components.alexa.state_report] Error when sending ChangeReport to Alexa: INVALID_ACCESS_TOKEN_EXCEPTION: Access token is not valid.

I have been receiving this error also.

The same for me. Adding client_id and client_secret does not seem to be the problem. But activating the “Send Alexa Events” toggle in the Skill’s Permissions is the cause that linking is not possible anymore.

I tried the same yesterday and got the same error. I was thinking it was my mistake. However, disabling proactive doesn’t seems to help. I still not able to link my account.

1 Like

I disabled my HAASKA skill and re-enabled it and the errors are gone. Not sure if people using Alexa with HA cloud get it or it is just HAASKA integration.

Found something: see here.

In addition, if you enable the Send Alexa Events permission for the skill, your Lambda function must handle the AcceptGrant directive. If your skill does not handle this directive, account linking fails when the user attempts to enable your skill. See Authenticate a Customer to Alexa with Permissions

The lambda function from @awarecan does not seem to handle this directive. See here

1 Like

I don’t think this is the error, I made a change to the lambda according to the alexa dev docs and still get the error.

If you want to try (but is not working for everyone, just left as reference)

"""
Copyright 2019 Jason Hu <awaregit at gmail.com>

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import os
import json
import logging
import urllib3

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

_logger = logging.getLogger('HomeAssistant-SmartHome')
_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'

    directive = event.get('directive')
    assert directive is not None, 'Malformatted request - missing directive'
    assert directive.get('header', {}).get('payloadVersion') == '3', \
        'Only support payloadVersion == 3'
        
    grant = directive.get('header', {}).get('name')
    if grant is 'AcceptGrant':
        return {
            'event': {
                'header': {
                    'messageId': directive.get('header', {}).get('messageId'),
                    'namespace': 'Alexa.Authorization',
                    'name': 'AcceptGrant.Response',
                    'payloadVersion': '3'
                },
                'payload': {
                }
            }
        }
    
    scope = directive.get('endpoint', {}).get('scope')
    if scope is None:
        # token is in payload for Discovery directive 
        scope = directive.get('payload', {}).get('scope')
    assert scope is not None, 'Malformatted request - missing endpoint.scope'
    assert scope.get('type') == 'BearerToken', 'Only support BearerToken'

    token = scope.get('token')
    if token is None and _debug:
        token = os.environ.get('LONG_LIVED_ACCESS_TOKEN')  # only for debug purpose
    
    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/smart_home'.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'))

It looks like the developers were quick in fixing it for cloud but no urgency for haaska integration, pity.

I tried the above but it still won’t link

I’m using cloud and I get this error but I only seem to get it when I tell alexa to set a colour light to white. When I do that, the light goes white but then alexa says “I don’t know what went wrong” and reports this in the logs. All other colours trigger a success chime from alexa, but still logs invalid access token in the logs. If I do it in the app, most colours work fine, the white ones say “server was unresponsive”. Very odd

I opened an issue to hopefully catch attention from any dev:
https://github.com/home-assistant/home-assistant/issues/24867

2 Likes

The same for me. Also if I use your lambda, as soon as I activate “Send Alexa Events” in the Skill I am unable to link.

I just restarted from scratch with hass.io (0.95.4) and I’m unable to link after following the guide at https://www.home-assistant.io/components/alexa.smart_home

Had no issues with previous builds and haaska but wanted to link through HA and oauth.

Are you from US with an Amazon US account? Just asking to try to know why some people can link and some not.

Hi!
For all having problems linking: For me, this lambda seems to be working ok (from here). Environment variables HOST and BEARER_TOKEN (long lived acces token) must be set. Handler is called lambda_function.event_handler
Can anyone confirm? Than maybe we can improve it to use the HA authentication instead of the long lived token.

@matt2005

Please try to add following between line 40 and 41 to the lambda function from @awarecan:

    if scope is None:
        # token is in grantee for Linking directive 
        scope = directive.get('payload', {}).get('grantee')

seem to work for me and I don’t need the long lived access token.

Yes, US with US Amazon account.

Doesn’t seem to work for me.

it is now linking using the modified script
github gist

below is my configuration.

AWS region Ireland

#secrets.yaml
alexa_event_endpoint: "https://api.eu.amazonalexa.com/v3/events"
alexa:
  smart_home:
    endpoint: !secret alexa_event_endpoint
    client_id: !secret alexa_client_id
    client_secret: !secret alexa_client_secret

Can you confirm that you have “Send Alexa Events” enabled?
I used your code and I have the same endpoint but it doesn’t link :frowning: