11
votes

I am creating custom skill in Alexa which uses account linking. I have created my own authentication server using OAuth2 php library and I have configured the authorization url and token urls in skill configuration.

When I try account linking from Alexa mobile app, I get error 'unable to link your skill'. following is my work progress.

  • Alexa app is able to open my authentication url.
  • I am able authorize and provide authorization code with redirect uri.
  • Alexa is requesting for access token using authorization code previously provided.
  • I am able validate authorization code and response back with access token and refresh token.
  • Alexa fails in this step to link with my skill. It say's 'Unable to link your skill'.

I have gone through my forums about the same, but couldn't find what exactly the issue is. Could any one please help me out in this regard.

6
Do you have an example of the redirect url? Specifically the query string.Jay Hewitt
layla.amazon.com/api/skill/link/… . This is how my redirect look like while authorizingArun
Amazon's official documentation for such issues: forums.developer.amazon.com/articles/38610/…psykid
were you able to fix this issue? I am facing the same issue with my custom skill. While trying to link the account, it redirects to Unable to link the account. I am using Authorization code grant type and have updated client secret as well. any help would be appreciated.charsi

6 Answers

3
votes

I was facing the same issue too , the problem was solved by selecting "credentials in request body" (default being Http basic) for "Client Authentication Scheme", since the access token in my case was sent in the body of the message. Check how the authentication token is sent by your server.

2
votes

If your redirect link is currently:

https://layla.amazon.com/api/skill/link/xxxxxxxxxxxxxx?code=xxxxxxxxx&state=xxxxx

You need to change the ? to a #

e.g.

https://layla.amazon.com/api/skill/link/xxxxxxxxxxxxxx#code=xxxxxxxxx&state=xxxxx

1
votes

Thought this might help anyone wondering how the Alexa service is posting to their OAuth endpoint since it's pretty opaque and undocumented. The redirect to the Alexa service initiates a POST request to the defined OAuth endpoint with the post body in x-www-form-urlencoded format not JSON. So the POST looks like this. ​

POST /authentication/1/oauth HTTP/1.1 url.Values{} grant_type=authorization_code&code=XXXXXXXXXXXXXXXXXXXXXXXXX&redirect_uri=https%253A%252F%252Fpitangui.amazon.com%252Fapi%252Fskill%252Flink%252FM9BEOG3DM65SQ&client_id=XXXXXXXXXXXXXXXXXXXXXX

If your endpoint isn't parsing this data or expecting some format that can be unmarshaled easily then it is probably failing with a 406 response.

0
votes

In my case the problem was with the Client secret, In google developer console add your skill redirect URIs and recheck the client secret you provide in the alexa skill Authorization grant type

0
votes

My issue was with the final AccessToken call. I was assuming it was using a GET request, so I only catered for this in my function. It is actually creating an access token. So it's using a POST.

After I updated my function to use a post and return the AccessToken in JSON format it all works fine.

0
votes

Maybe the following steps will help you identify the problem:

  • Add console.log('LOGS', response) to your Lambda function.
  • Activate the skill and login in the Alexa app
  • Go back to your Lambda function and check the last logs for the LOGS entry.

If you find that the Lambda function is invoked than the problem is not from your OAuth server, but you may need to handle the "AcceptGrant directive" in your Lambda function as it is motioned here: https://developer.amazon.com/en-US/docs/alexa/device-apis/alexa-authorization.html#directives

adjust your Lambda function to:

exports.handler = function (request, context) {

if (request.directive.header.namespace === 'Alexa.Authorization' && request.directive.header.name === 'AcceptGrant') {
    log("DEBUG:", "Authorization request",  JSON.stringify(request));
    handleAcceptGrant(request, context);
}

function handleAcceptGrant(request, context) {
    var response = {
        event: {
            header: {
                "namespace": "Alexa.Authorization",
                "name": "AcceptGrant.Response",
                "messageId": request.directive.header.messageId,
                "payloadVersion": "3"
            },
            payload: {}
        }
    };
    log("DEBUG", "Alexa.Authorization ", JSON.stringify(response));
    context.succeed(response);
}

If the problem is with the AcceptGrant then The account linking should be now successful.