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:
CapabilitiesDelegate::create()
- Authorizes theCapabilitiesDelegate
to publish the capabilities of the device.DefaultClient::create()
- Authorizes the Alexa Communications Library (ACL) to send requests to AVS.
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.
CustomerDataManager
to manage all CustomerDataHandler
objects so that the application don't have to manually call clearData()
independently.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

To integrate AuthDelegateInterface with a companion app to retrieve access tokens
- Check for a valid Refresh Token token. If you already have a valid refresh token, skip to step 7.
- Load the
Product ID
andDevice Serial Number
parameters. - Generate a Code Verifier and Code Challenge pair. Retain for use in later steps.
- 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
, andCode Challenge
.
- After connecting, get the
- Using the Companion App, send the
Authorization Code
,Client ID
, andRedirect URI
to your product. Implement this functionality in the manner that best fits your product. Retain these values for use in later steps. - Get an Access token and Refresh Token. Send a
POST
request to the LWA. - The Access Token and Refresh Token can expire. To refresh them, send a
refresh token POST
request to the LWA.
AuthDelegateInterface
has a method to restart the authorization process.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

To create a custom implementation of CBL
- Load the
Client ID
,Product ID
andDevice Serial Number
parameters. - Check for a valid Refresh Token. If you have one, skip to step 5.
- Send a Device Authorization Request to LWA. For more details, see Device Authorization Request.
- 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.
- 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.
Related topics
- Authorize from an AVS Product (Android/iOS)
- Authorize an AVS Device Through a Companion App
- Authorize an AVS Device Through Code-Based Linking
Last updated: Sep 28, 2022