Alexa Voice Service Device SDK Authorization


The Alexa Voice Service (AVS) Device SDK uses Login with Amazon (LWA) to authorize your client's requests with one of the following protocols:

To authenticate the SDK with LWA, your device sends an access token to AVS with every request. The SDK abstracts the token retrieval process by using the AuthDelegateInterface. This abstraction enables the SDK to work with any of the existing methods to acquire access tokens. It also allows you to specialize your implementation of AuthDelegateInterface without changing the code that relies on the AuthDelegateInterface.

How AuthDelegateInterface works

You inject an instance of AuthDelegateInterface into your product to abstract the LWA token retrieval process. How you implement this abstraction depends on the authorization method you're using.

If you've based your product on the sample app

The sample app uses code-based linking authorization. When the sample app initializes, it creates an instance of AuthDelegateInterface. Some methods used include:

To set your product up with code-based linking, inject your implementation of AuthDelegateInterface into the same places as the sample app.

If you haven't based your product on the sample app

If your product isn't based on the sample app, you're using the Companion App, companion site or the on-product authorization method. You must create a custom instance of AuthDelegateInterface. The AuthDelegateInterface is used to communicate with any components that need to send requests to the cloud, for example, the Alexa Communications Library (ACL).

To do this, pass your instance of AuthDelegateInterface into the MessageRouter constructor call.

Next, pass your MessageRouter instance into AVSConnectionManager::create(). AVSConnectionManager manages your persistent connection with AVS.

Required methods

AuthDelegateInterface contains abstract methods that you must use in your implementation.

Get an LWA authorization token

getAuthToken()

Every time you make a call to AVS, you must check if you have a valid token.

getAuthToken() returns the current access token.

  • Returns an empty string if it's your first time requesting a token or an access token expires.
  • Call getAuthToken() immediately before sending any messages to AVS.
  • Proper implementations of getAuthToken() preemptively refresh access tokens before they expire, meaning you can send requests to AVS without waiting for a refresh.

Example

virtual std::string getAuthToken() = 0;

Observe state changes

addAuthObserver() and removeAuthObserver()

It's important to observe any changes to the AuthDelegateInterface state. Observing prevents requests from failing due to an expired authorization token. Observing also informs your client when the authorization process restores.

To observe the AuthDelegateInterface state, use the following abstract methods: addAuthObserver() and removeAuthObserver().

When the authorization state changes, addAuthObserver() and removeAuthObserver() manage instances of AuthObserverInterface that receive notifications.

Example

virtual void addAuthObserver(std::shared_ptr<avsCommon::sdkInterfaces::AuthObserverInterface> observer) = 0;
virtual void removeAuthObserver(std::shared_ptr<avsCommon::sdkInterfaces::AuthObserverInterface> observer) = 0;

onAuthStateChange()

You report state changes to the observers with onAuthStateChange(). This method takes two parameters, the state and an error code. You can also receive callbacks when the state changes by calling setAuthObserver().

Parameter Description
State The new State of the authorization delegate.
Error code Error code that provides details about how the state.

Handle customer data

CustomerDataHandler()

Your implementation of AuthDelegateInterface must retain the current access token and refresh it before it expires. To obtain a refresh token, you might need to transfer device properties that might hold customer-specific data. After receiving the refresh token, you should minimize stored customer data and wipe any data that's not required for the refresh process.

To wipe customer data, implement an instance of the CustomerDataHandler interface and its abstract method clearData(). You must call clearData() for each instance of CustomerDataHandler. You should wipe the data when the user resets the product or if the primary user associated with the product changes.

Example

virtual void clearData() = 0;

One way to incorporate CustomerDataHandler into your implementation is to use multiple inheritance and derive your implementation from both AuthDelegateInterface and CustomerDataHandler.

Example

class MyAuthDelegate
        : public avsCommon::sdkInterfaces::AuthDelegateInterface
        , public registrationManager::CustomerDataHandler {
    ...
};

SDK authorization flows

Companion app

Companion app authorization is useful for headless devices, such as a smart speaker. It provides an interface for users to generate Authorization Codes and register device with AVS.

The AVS Device SDK doesn't provide a companion app – you must create one for your product.

Companion app data flow companion app data flow

To integrate AuthDelegateInterface with a companion app to retrieve access tokens

  1. Check for a valid Refresh Token token. If you already have a valid refresh token, skip to step 7.
  2. Load the Product ID and Device Serial Number parameters.
  3. Generate a Code Verifier and Code Challenge pair. Retain for use in later steps.
  4. Connect your product to the Companion App using a supported protocol, such as Bluetooth or Wi-Fi. Implement this functionality in the manner that best fits your product.
    • After connecting, get the Product ID, Device Serial Number, and Code Challenge.
  5. Using the Companion App, send the Authorization Code, Client ID, and Redirect URI to your product. Implement this functionality in the manner that best fits your product. Retain these values for use in later steps.
  6. Get an Access token and Refresh Token. Send a POST request to the LWA.
  7. The Access Token and Refresh Token can expire. To refresh them, send a refresh token POST request to the LWA.

Get token

Gets an Access Token and Refresh Token from the LWA server.

Sample request

POST: https://api.amazon.com/auth/O2/token
Parameter Description
grant_type authorization_code
code The authorization code received from the companion app
redirect_uri The Redirect URI received from the companion app
client_id The Client ID received from the companion app
code_verifier The Code Verifier initially generated by the product

Sample response

If this request times out or fails due to a server error, retry after a delay until it succeeds or the product shuts down.

HTTP/1.1 200 OK
Content-Type: application/json;charset UTF-8
 {
    "access_token":"...",
    "refresh_token":"Atzr|IQEBLzAtAhRPpMJxdwVz2Nn6f2y-tpJX2DeX..."
    "token_type":"bearer",
    "expires_in":3600,
    "code_verifier: "..."
 }
Parameter Description
access_token The access token
refresh_token The refresh token
token_type bearer
expires_in The number of seconds for which the access token is still valid

Refresh token

Refreshes an Access Token and Refresh Token from the LWA server.

Sample request

POST: https://api.amazon.com/auth/O2/token
Parameter Description
grant_type refresh_token
refresh_token The refresh token
client_id The Client ID received from the companion app

Sample response

HTTP/1.1 200 OK
Content-Type: application/json;charset UTF-8
 {
    "access_token":"...",
    "refresh_token":"Atzr|IQEBLzAtAhRPpMJxdwVz2Nn6f2y-tpJX2DeX..."
    "token_type":"bearer",
    "expires_in":3600,
 }
Parameter Description
access_token The access token
refresh_token The refresh token
token_type bearer
expires_in The number of seconds for which the access token is still valid

Code-based linking (CBL)

The AVS Device SDK sample app provides an example implementation of the CBL.

The AVS Device SDK provides default implementation for the CBL in the LWAAuthorizationAdapter class. This class implements AuthorizationAdapterInterface for integration with the AuthorizationManager framework. AuthorizationManager allows use of other authorization methods, or custom implementations for CBL authorization. To add a new authorization method or replace an existing implementation, the new class must implement the AuthorizationAdapterInterface and be registered with AuthorizationManager the same way as how the LWAAuthorizationAdapter is registered in the SampleApplication class.

CBL data flow CBL data flow

To create a custom implementation of CBL

  1. Load the Client ID, Product ID and Device Serial Number parameters.
  2. Check for a valid Refresh Token. If you have one, skip to step 5.
  3. Send a Device Authorization Request to LWA. For more details, see Device Authorization Request.
  4. Prompt the user to visit your Verification URI and enter the User Code. For more details, see Direct the user to log in for details.
  5. At the same time that the user is entering User Code, poll LWA to acquire an initial access token by sending Device Token Requests to LWA. For more details, see Device Token Request.

On product

To create your own implementation of the On Product authorization, you must provide an implementation of AuthDelegateInterface that uses the Android or iOS LWA Library operations described in the On Product documentation.


Was this page helpful?

Last updated: Sep 28, 2022