Voice-Forward Account Linking Implementation Details (LWA)

If your skill supports voice-forward account linking, your skill must handle the following interactions with Alexa:

To see the point in the flow at which your skill must do these tasks, see Flow for voice-forward account linking. For a walkthrough of how to implement voice-forward account linking, see Tutorial: Implement Voice-Forward Account Linking in Your Skill (LWA).

Implement a handler to request the task to initiate voice-forward account linking

In step 1 of the voice-forward account linking flow, your skill uses skill connections to request the Amazon-owned voice-forward account linking skill to perform a task. In this case, the task (AMAZON.AskForAccountLinking) for the Amazon-owned voice-forward account linking skill is to link the customer's account.

In skill connections terms, your skill is the requester, and the Amazon-owned voice-forward account linking skill is the provider.

You must first determine when to begin the account linking experience. Then, to pass the control to the Amazon-owned voice-forward account linking skill, your skill must implement a handler to return a Connections.StartConnection directive as shown in the following example. The RESUME_SESSION flag means that Alexa passes control back to your skill when the task is complete. For details, see Request a task from a provider skill.

const LinkMyAccountRequestHandler = {
  canHandle(handlerInput) {
    const request = handlerInput.requestEnvelope.request;
    return request.type === 'IntentRequest'
      && request.intent.name === 'LinkMyAccount';
  },
  handle(handlerInput) {
    var accessToken = handlerInput.requestEnvelope.context.System.user.accessToken;
    if (accessToken == undefined){
       //Account is not linked
        return handlerInput.responseBuilder
        .speak(<value_prompt>)
        .addDirective({
            'type': 'Connections.StartConnection',
            'uri': 'connection://AMAZON.AskForAccountLinking/1',
            'onCompletion': 'RESUME_SESSION',
            'input': {
            '@version': '1',
            '@type': 'AskForAccountLinking'
            },
            'token': 'accountLinking'
            // Token can be anything that can be used to identify the request on session resumption
        })
            .getResponse();
    }else{
      // Handle the account already linked flow.
    }
  }
};

Implement a handler to get the response on the task to initiate voice-forward account linking

In step 3 of the voice-forward account linking flow, the voice-forward account linking flow completes. Your skill session with the customer resumes because you set the onCompletion flag in the skill connections request to RESUME_SESSION. Your skill receives the skill connection response in the form of a Tasks.CompleteTask directive in the following form.

{
    "type": "Task.CompleteTask",
    "status": {
        "code": "string",
        "message": "string"
     }
    "token": "string"
    "result": {
      "status" : <account_linking_status_enum>
    }
}

The status object returned by the "Voice Forward Account Linking" skill can contain the following codes and messages.

Status Message Alexa response before transferring control to your skill

200

User account was already linked

"Since you have already given [skill name] permission to access your email address, I've signed you in using Login with Amazon. You can manage your linked account by going to the skills section of your Alexa app."

200

User account is now linked

"Great, [person's name]. I've signed you in with [skill name] using Login with Amazon. You can manage your linked account by going to the skills section of your Alexa app."

200

User denied account linking request

"Okay, you can link your account at any time by going to the skills section of your Alexa app."

200

User hasn't enabled skills personalization

"To link your account with [skill name], go to the skills section of your Alexa app. In the future, you can link your account using voice by setting up your Voice ID from 'Your Profile and Family' in the Settings of your Alexa app."

200

User isn't the Amazon account owner

"Hm, only the primary account owner can use voice to link their accounts. You can link your [skill name] account by going to the skills section of your Alexa app."

200

User didn't answer the account linking request

"Okay, you can link your account at any time by going to the skills section of your Alexa app."

400

Bad Request, request is invalid.

"To link your account to [skill name], go to the skills section of your Alexa app."

403

Requester wasn't allowed to invoke the provider

"To link your account to [skill name], go to the skills section of your Alexa app."

500

Internal Server error

"Sorry, something went wrong. To link your account with [skill name], go to the skills section of your Alexa app."

Your skill must also implement a handler to receive a skill connection response from the Amazon-owned voice-forward account linking skill, and use that response to appropriately continue the conversation for your customer based on the result of the voice-forward account linking flow. Keep in mind the following best practices:

  • Avoid re-initiating voice-forward account linking for a customer in the same skill session. In other words, don't use the following handler to send the customer back into the voice-forward account linking experience. You can instead send an account linking home card to allow the customer to link their account at a later stage.

  • If a customer was not successfully linked after the voice-forward account linking flow, you should send a LinkAccount card that lets customers start the account linking experience from their Alexa app at a later time. For details about account linking cards, see Define a card for use with account linking.

  • After the customer's account is successfully linked (that is, accountLinkingTaskStatus is LINKED), use the account linking accessToken to retrieve the LWA user_id. You can use the retrieved LWA user_id to determine whether you need to register the customer as a new customer within your system.

To receive the skill connection response on the AMAZON.AskForAccountLinking task, implement a handler of the following form.

const AccountLinkingSessionResumedHandler = {
    canHandle(handlerInput) {
        const request = handlerInput.requestEnvelope.request;
    return request.type === 'SessionResumedRequest' && request.cause.token === 'accountLinking'; // Token needs to be same as passed in request
    },
    handle(handlerInput) {
       const status = handlerInput.requestEnvelope.request.cause.status;
       const code = status.code;
       const message = status.message;
       console.log(`AccountLinkingSessionResumedHandler received status code : ${code} and message : ${message}`);

       const accountLinkingStatus = handlerInput.requestEnvelope.request.cause.result.status;

       if (code !== '200'){
        //Error occured in the request
        //Response
        return handlerInput.responseBuilder
            .speak(speechText)
            .withLinkAccountCard()
            .getResponse();
       }

       // Now check to see if the user passed or failed account linking.
        const accountLinkingTaskResult = handlerInput.requestEnvelope.request.cause.result;
        const accountLinkingTaskStatus = accountLinkingTaskResult.status;        
        if (accountLinkingTaskStatus === 'LINKED') {
         // Account was linked or is linked successfully as part of the request
         // <HANDLE_LINKED>
         //Response
        var accessToken = handlerInput.requestEnvelope.context.System.user.accessToken;

        // Logic to look up or create account if necessary
        // If you have a resource server that makes call internally to LWA to get the LWA ID
        // makeHttpCall('resource_server',accessToken);

        // If you need LWA_ID for your operation
        // https://developer.amazon.com/docs/login-with-amazon/obtain-customer-profile.html#call-profile-endpoint
        // makeHttpCall('https://api.amazon.com/user/profile?access_token=*',accessToken);
        // Use LWA_ID from the request above to look up or create an account as necessary

        // If you need customer contact information, use the Alexa Customer Profile API
        // https://developer.amazon.com/en-US/docs/alexa/custom-skills/request-customer-contact-information-for-use-in-your-skill.html

        return handlerInput.responseBuilder
            .speak(speechText)
            .getResponse();

        } else if (accountLinkingTaskStatus === 'DENIED') {
        // User denied the account linking permissions on request or sharing the information with the skill, hence the account linking flow failed.

        // <HANDLE_DENIED>
        //Response
        return handlerInput.responseBuilder
            .speak(speechText)
            .withLinkAccountCard()
            .getResponse();

        } else if (accountLinkingTaskStatus === 'NOT_ANSWERED') {
          // The user did not answer the question, asked as part of the skill.
          // <HANDLE_NOT_ANSWERED>
          //Response
        return handlerInput.responseBuilder
            .speak(speechText)
            .withLinkAccountCard()
            .getResponse();
        } else if (accountLinkingTaskStatus === 'USER_REQUIREMENTS_NOT_MET'){
          // The request was cancelled because the voice account linking flow can't be triggered for the customer or can't be completed.
          // <HANDLE_USER_REQUIREMENTS_NOT_MET>
          //Response
        return handlerInput.responseBuilder
            .speak(speechText)
            .withLinkAccountCard()
            .getResponse();
        }

    }
};