Vielen Dank für Ihren Besuch. Diese Seite ist momentan nur auf Englisch verfügbar. Wir arbeiten an der deutschen Version. Vielen Dank für Ihr Verständnis.

Validate and Use Access Tokens in Custom Skill Code

Once a user successfully enables your skill and links their Alexa account with the other service, requests sent to your skill include the user's access token (accessToken). Add logic to the service for your skill to verify and use this access token.

This document covers account linking logic for custom skills. If you are working on a smart home or video skill, see Validate and Use Access Tokens in Smart Home and Video Skill Code.

Decide Which Requests Require Account Linking

A custom skill can require authentication (and therefore a valid access token ) on all requests, or on just some requests. This depends on your skill's design and functionality.

For example, the Car Fu skill might require user authentication to order a car, but does not require authentication to just ask whether the service is available in a particular city. Therefore, the code for this skill might do the following:

  • The handler for the OrderCar intent checks for a valid accessToken and uses that token to retrieve the user's Car Fu profile and order a car.
  • The handler for the CarFuAvailabilityByCity intent looks up public information on the Car Fu service and returns a response. This handler does not need to check for an accessToken.
  • The handler for the LaunchRequest provides an intro to the skill and asks the user what they want to do. This handler does not need to check for an accessToken.

For requests that require authentication, do the following:

  1. Get the access token from the request
  2. Validate the token and authenticate the user
  3. Return a link account card and user-friendly output speech if the token is not present or is invalid.

For intents that do not require authentication, you can skip these steps and just provide a normal response.

Required Account Linking

Some skills have no alternate functionality to offer if the user has not linked their account. In this case, every request needs to check for the access token and return an appropriate prompt and link account card if the user has not linked their account:

User: Alexa, open Car Fu.
Alexa: Welcome to Car Fu. To use this skill, you must have a Car Fu account. I've sent some information to the Alexa app. Open your Alexa app and click on the link to connect your Car Fu account with Alexa.
Session ends.

Optional Account Linking

One way to encourage optional account linking is to explain the benefits of connecting to the user account and ask the user if they want to proceed. The welcome message you return in your LaunchRequest is a good place to do this. For example:

User: Alexa, open Car Fu.
Alexa: Welcome to Car Fu. If you have a Car Fu account, I can order you a ride. Do you want to set that up now?
User: Yes. (This sends the built-in AMAZON.YesIntent)
The skill sends the link account card, as discussed in Respond to the User if the Token is Invalid or Missing

Alexa: OK, I've sent some information to the Alexa app. Open your Alexa app and click on the link to connect your Car Fu account with Alexa.
Session ends.

If the user responds with "no," your skill can offer alternate functionality that does not require an account:

User: Alexa, open Car Fu
Alexa: Welcome to Car Fu. If you have a Car Fu account, I can order you a ride. Do you want to set that up now?
User: No.
Alexa: OK, without a Car Fu account, I can tell you the cities where our service is available. You can ask for a specific city, or ask for our most recently added cities. Which do you want?
Conversation with the user continues…

Get the Access Token from the Request

If the user has successfully linked their account, the user's access token (accessToken) is included in each request sent to your skill. If they have not yet linked their account, the accessToken property is not included in the request.

The token is available in the accessToken property of the user object, which is available in the context object. The context object is included in all requests. You can access the accessToken in context.System.user.accessToken.

In this example, the user's accessToken is "Atza|AAAAAABBBBBBCCCCCC". Note that a real access token is typically much longer than this. Some objects within the request are not shown for brevity:

{
  "version": "1.0",
  "session": {},
  "context": {
    "AudioPlayer": {
      "playerActivity": "IDLE"
    },
    "Display": {},
    "System": {
      "application": {
        "applicationId": "amzn1.ask.skill.1111111-2222-3333-4444-5555555"
      },
      "user": {
        "userId": "amzn1.ask.account.XXXXXXXXXX",
        "accessToken": "Atza|AAAAAABBBBBBCCCCCC"
      },
      "device": {},
      "apiEndpoint": "https://api.amazonalexa.com",
      "apiAccessToken": "zzzzzzzzzz.yyyyyyyyyy.xxxxxxxxxx"
    }
  },
  "request": {}
}

Do not confuse the accessToken with the apiAccessToken included on all requests. The apiAccessToken is used for Alexa Skills Kit APIs such as the Device Address API and Progressive Response API.

The following examples show how you can retrieve the access token with either the Alexa Skills Kit SDK for Node.js or the Alexa Skills Kit SDK v2 for Java.

This example shows how you access the accessToken in the Alexa Skills Kit SDK v2 for Node.js. In this version of the SDK, you create request handlers to handle your intents.

const OrderCarIntentHandler = {

    //...

    handle(handlerInput){
        // This intent requires an access token so that we can get the user's
        // Car Fu user profile with payment information.

        // The access token is in the Context object. Access the
        // request in the HandlerInput object passed to the
        // handler.

        var accessToken = handlerInput.requestEnvelope.context.System.user.accessToken;

        // ...
    }
};

This example shows how you access the accessToken in the Alexa Skills Kit SDK v2 for Java. In this version of the SDK, you create request handlers to handle your intents. A request handler is a class that implements the RequestHandler interface.


public class OrderCarIntentHandler implements RequestHandler {
    // ...

    @Override
    public Optional<Response> handle(HandlerInput handlerInput) {

        // This intent requires an access token so that we can get the user's
        // Car Fu user profile with payment information.

        // The access token is in the Context object. Access the
        // request in the HandlerInput object passed to the
        // handler.

        String accessToken = handlerInput
                .getRequestEnvelope()
                .getContext()
                .getSystem()
                .getUser()
                .getAccessToken();

        // ...handler continues
    }
}

Validate the Access Token

For a request that requires authentication, your code should do at least two checks:

  1. Verify that the accessToken exists.
  2. Verify that the token represents a valid user in your resource server .

Verify that the Token Exists

Make sure that the accessToken exists. If the accessToken property is not included in the request, this means that the user has not yet successfully linked their account.

In the Alexa Skills Kit SDK for Node.js, the accessToken property on the user (for example, handlerInput.requestEnvelope.context.System.user.accessToken) returns undefined if the token does not exist. In the Alexa Skills Kit SDK v2 for Java, User.getAccessToken() returns null if the token does not exist.

Verify that the Token is Valid

If the accessToken exists, verify that it identifies a user in your resource server . The token could become invalid for multiple reasons, for example:

  • The user deleted or canceled their account with your service. For example, an Alexa user might have set up account linking with Car Fu, then later canceled their Car Fu account. At this point, the token stored by the Alexa service would identify a non-existent user.
  • The token has expired, and the Alexa service was unable to obtain a new token. This can occur with authorization code grant if your authorization server does not provide refresh tokens. This can also occur if you use implicit grant , which does not support refresh tokens.

If the token is valid, handle the request normally. You can use the token to access data from your resource server as needed. In the Car Fu example, the skill would retrieve profile and payment information for the user from the Car Fu service, order a car, and return a confirmation to the user. See Return a Response for details.

Respond to the User if the Token is Invalid or Missing

If the access token does not exist or is invalid on a request that requires authentication, return a response containing the following:

  • Output speech text explaining to the user that they need to link their account to use this feature. Succinctly explain the benefit of account linking in the speech text.
  • A link account card . This is a special type of card that tells the user to link their account. When displayed in the Alexa app, this card displays a link to your authorization URI . The user can start the account linking process right from this card.

In your JSON response include the card property with the type set to LinkAccount:

{
    "version": "1.0",
    "sessionAttributes": {},
    "response": {
      "outputSpeech": {
        "type": "PlainText",
        "text": "You must have a Car Fu account to order a car. Please use the Alexa app to link your Amazon account with your Car Fu Account."
      },
      "card": {
        "type": "LinkAccount"
      },
      "shouldEndSession": true
    }
}

Any additional card properties, such as cardTitle, are ignored.

The following examples show how to return a link account card with either the Alexa Skills Kit SDK for Node.js or the Alexa Skills Kit SDK v2 for Java.

The OrderCarIntentHandler function in this example checks for the presence of the access token and returns the link account card if it does not exist.

const OrderCarIntentHandler = {
  
  // ...

  handle(handlerInput){

    // This intent requires an access token so that we can get the user's
    // Car Fu user profile with payment information.

    // The access token is in the Context object. Access the
    // request in the HandlerInput object passed to the
    // handler.

    var accessToken = handlerInput.requestEnvelope.context.System.user.accessToken;

    if (accessToken == undefined){
        // The request did not include a token, so tell the user to link
        // accounts and return a LinkAccount card
        var speechText = "You must have a Car Fu account to order a car. " + 
                    "Please use the Alexa app to link your Amazon account " + 
                    "with your Car Fu Account.";        
        
        return handlerInput.responseBuilder
            .speak(speechText)
            .withLinkAccountCard()
            .getResponse();
    } else {

        // Use the token to access the user's profile. This should also verify that the
        // token represents a valid Car Fu user.

        // ...

    }
  }
};

The OrderCarIntentHandler function in this example checks for the presence of the access token and returns the link account card if it does not exist.

public class OrderCarIntentHandler implements RequestHandler {
    
    // ...

    @Override
    public Optional<Response> handle(HandlerInput handlerInput) {

        // This intent requires an access token so that we can get the user's
        // Car Fu user profile with payment information.

        // The access token is in the Context object. Access the
        // request in the HandlerInput object passed to the
        // handler.

        String accessToken = handlerInput
                .getRequestEnvelope()
                .getContext()
                .getSystem()
                .getUser()
                .getAccessToken();

        if (accessToken != null) {
            // Call a method to validate the token, get the user's Car Fu
            // profile and order a ride
            return orderCarForUser(accessToken, handlerInput);
        } else {
            // The request did not include a token, so tell the user to link
            // accounts and return a LinkAccount card

            String speechText = "You must have a Car Fu account to order a car. "
                    + "Please use the Alexa app to link your Amazon account "
                    + "with your Car Fu Account.";

            // Build a response with output speech and a LinkAccount card.        
            return handlerInput.getResponseBuilder()
                    .withSpeech(speechText)
                    .withLinkAccountCard()
                    .build();
        }
    }
}

In most cases, this response should end the session, since the user cannot continue with their request until after they have linked their account. If your skill includes some intents that don't require authentication, it may make sense to ask the user a different question and keep the session open.

OAuth Resources:

Other Resources: