LWA Integration Tasks

📘

Important

The Buy with Prime API is offered as a preview and might change as we receive feedback and iterate on the interfaces. We are sharing this early documentation to help you learn about the Buy with Prime API as we write and iterate on the content.

To customize the Buy with Prime experience to shoppers on your site, you can integrate your site with Login with Amazon (LWA). LWA enables shoppers to sign in using their Amazon account credentials. Alternatively, you can integrate your site with Amazon Pay. For details, see Manage Shopper Identity.

This topic contains a collection of implementation tasks that apply to integrating your site with LWA. Not all of these tasks apply to your use case. The required tasks depend on two choices:

  • URL type: The sign-in page that shoppers start from can have a static URL or a dynamic URL. A static URL, such as https://www.example.com/checkout, doesn't have any parameters. A dynamic URL, such as https://www.example.com/product/red-shirt-1, has parameters that change.
  • LWA integration method: You can integrate with LWA in three ways: directly, with an LWA SDK, or with the Buy with Prime UI library, which provides pre-built UI components. For details on which method to choose, see Use Login with Amazon for Shopper Identity.

In any case, to find your list of implementation tasks, see the page for the applicable integration method:


Set up a security profile

Before you can use LWA, you must set up an LWA security profile for your website. For instructions, see Set up an LWA security profile.

An important part of setting up a security profile is to add the appropriate URLs to the Allowed Return URLs. The values that you add to Allowed Return URLs depend on whether you add the sign-in link to pages with static URLs or dynamic URLs.

  • For static URLs, add the static URL (such as https://www.example.com/cart) to the Allowed Return URLs.
  • For dynamic URLs, add your redirect handler URL (such as https://www.example.com/bwp-signin-redirect) to the Allowed Return URLs.

Send requests

This section describes calls that you make to LWA endpoints during the authentication process. If you integrate with LWA directly, you make the calls directly. If you use an LWA SDK, you use the SDK to make the call. If you use the Buy with Prime UI Library, the delivery card UI component makes the requests on your behalf.

Send an authorization request

URL TypeRequired Task?
Static URLsYes, unless you use the Buy with Prime UI library
Dynamic URLsYes, unless you use the Buy with Prime UI library

To request an authorization code, send an HTTPS request to Amazon's authorization server (https://www.amazon.com/ap/oa) in the following form.

https://www.amazon.com/ap/oa?
client_id=YOUR_CLIENT_ID
&scope=YOUR_SCOPES
&response_type=code
&state=YOUR_STATE
&redirect_uri=YOUR_REDIRECT_URL
&code_challenge=YOUR_CODE_CHALLENGE

For details about all of the parameters, see Authorization Request. The following sections focus on the parameter values to integrate with LWA in the Buy with Prime scenario.

client_id parameter

Set this to the client ID associated with your LWA security profile. For details, see Get Your LWA Security Profile Information.

scope parameter

Set the scope parameter to the following string, which is the concatenation of the scope values in the authorization code request, with the scope values separated by spaces (%20).

profile%20profile:default_shipping_address%20profile:mobile_number%20buywithprime::merchant_orders

The following table describes the scope values.

Scope ValuePermission Represented
buywithprime::merchant_ordersPermission to access the shopper’s information to call certain Buy with Prime API interfaces, such as the deliveryPreview query, the order query, and so on.
profilePermission to access the shopper's name and email address.
profile:default_shipping_addressPermission to access the shopper's default shipping address, if available.
profile:mobile_numberPermission to access the shopper's phone number, if available.

response_type parameter

Set this to code.

state parameter

To protect against cross-site-request-forgery (CSRF) attacks and (in the case of dynamic redirects) record the dynamic URL, include a state parameter in the authentication request. For details about how to calculate the state, see Generate and store a state.

You must have this parameter for dynamic redirection.

redirect_uri parameter

For static URLs, set the redirect_uri parameter to the static URL. For example, set the redirect_uri to https://www.example.com/cart . You can either hard-code the URL directly or use windows.location.href if the redirect URL is the current page.

For dynamic URLs, set the redirect_uri to your redirect handler.

Make sure you add the redirect_uri to the Allowed Return URLs in your security profile settings in the LWA console. For details, see the documentation on handling redirects and token exchanges.

code_challenge parameter

This parameter is recommended, and is required in browser-based applications. First, generate the code_verifier as a cryptographically random string using the characters A-Z, a-z, 0-9, and the punctuation characters -._~ (hyphen, period, underscore, and tilde), between 43 and 128 characters long. Then, generate the code_challenge as a base64 URL-encoded string of the SHA256 hash of the code_verifier.

Example code to generate a code_challenge parameter
// Dependency: Node.js crypto module
// https://nodejs.org/api/crypto.html#crypto_crypto
function base64URLEncode(str) {
  return str.toString('base64')
      .replace(/\+/g, '-')
      .replace(/\//g, '_')
      .replace(/=/g, '');
}
var code_verifier = base64URLEncode(crypto.randomBytes(32));

// Dependency: Node.js crypto module
// https://nodejs.org/api/crypto.html#crypto_crypto
function sha256(buffer) {
  return crypto.createHash('sha256').update(buffer).digest();
}
var code_challenge = base64URLEncode(sha256(code_verifier));
Example code to send an authorization request

To send the authorization request, you can trigger the redirection as follows.

window.location.replace("<https://www.amazon.com/ap/oa?client_id=foodev&scope=profile%20profile:default_shipping_address%20profile:contact%20buywithprime::merchant_orders&response_type=code&state=YOUR_STATE&redirect_uri=https://www.example.com/cart&code_challenge=YOUR_CODE_CHALLENGE&code_challenge_method=S256")>;

Alternatively, you can have a handler responsible for building the query parameters for the authorization request, and use Ajax to handle the redirection.

<script>
$(document).ready(function(){
  $("button").click(function(){
    $.ajax({
    url: "/authorize_handler", // Your handler for the ajax call that formats the authorization request
    type: "POST",
    data: {
      "redirect_uri": "https://www.example.com/cart"
    }
    success: function(result,status,xhr){
      if (xhr.status == 302) {
        window.location.replace(result);
      }
    }});
  });
});
</script>

Send an access token request

URL TypeRequired Task?
Static URLsYes
Dynamic URLsYes

To exchange an authorization code for an access token and refresh token, call the LWA North America token endpoint (https://api.amazon.com/auth/o2/token). For a list of parameters, see Access Token Request.

If you set a code_challenge in the authorization request, you must provide a code_verifier in the access token request.

After you get an access token and refresh token, you can persist the access token on the client side to make Buy with Prime API calls and get the shopper’s profile data. Because LWA access tokens expire in one hour, you can use the refresh token to get a new access token. We recommend that you save the refresh token in the backend session data to maintain continuous access to the access token. For details, see Using Refresh Tokens. You therefore can maintain the shopper's signed-in state for the current session. It's important to clear the stored shopper state from the session after the session ends or the shopper signs out.

The following code shows how to get the access token and refresh token.

Code Example to Get an Access Token and Refresh Token
const express = require('express'); 
const app = express();

// Store data in session management database.
async function saveToSessionDB(sessionId, data) {
 // Implement database-saving logic here.
}

// The client is requesting to load the redirect handler page.
app.post('/bwp-signin-redirect/:state/:code', (req, res) => {
const code = req.params.code;
const sessionId = req.sessionID; // Assumes session management middleware that assigns a session ID.
const redirectUrl= "https://www.example.com/bwp-signin-redirect";  

// ...other JavaScript code  

  if (state === storedState) {
    //...other JavaScript code    
 
    try {        
      // Get the LWA access token and refresh token.
      const oAuthToken = await getLWAOAuthToken(code, redirectUrl);
      // Save the access token and refresh token in the session database.
      await saveToSessionDB(sessionId, {'accessToken': oAuthToken.access_token});
      await saveToSessionDB(sessionId, {'refreshToken': oAuthToken.refresh_token});
     } catch (error) {
      // Implement error handling here
     }    
 // ...Remaining steps.
 }
});

// Get LWA oAuthToken with code and redirectUrl.
async function getLWAOAuthToken(code, redirectUrl) {
  
   try {
        // Define parameters for the OAuth token request.
        const params = new URLSearchParams({
            grant_type: 'authorization_code',
            code: code,
            client_id: 'amzn1.application-oa2-client.your-uniqe-client-id', // LWA client ID
            client_secret: 'LWA_CLIENT_SECRET', // LWA client secret
            redirect_uri: redirectUrl, // For example, https://www.example.com/bwp-signin-redirect
            code_verifier: 'CODE_VERIFIER', // code verifier, required if code challenge was provided in authorization request
        });  
  
        const response = await fetch('https://api.amazon.com/auth/o2/token', {
            method: 'POST',
            headers: {
               'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: params.toString(),
        });  
  
     if (!response.ok) {
         // Implement error handling here
     }    
     return await response.json();
     
 } catch (error) {
   // Implement error handling here.
 }
}

In the case of dynamic URLs, after the redirect handler gets the access and refresh tokens, it should redirect the shopper to the original page they were on.


Send a request for shopper data

URL TypeRequired Task?
Static URLsNo
Dynamic URLsNo

After you get an access token from the access token response, you can get the shopper's Amazon customer profile data, which includes the shopper's name, email, default shipping address (optional), and mobile number (optional). For details, see Call the Profile Endpoint Server-Side in the LWA documentation.

Example Code to Get a Shopper's Profile Data
const express = require('express'); 
const app = express();

//Function to get the date from a session database.
async function getFromSessionDB(sessionId, data) {
 // Your database logic to retrieve session data.
 return data_from_db; // Simulate retrieval
}


// The client is requesting to load the redirect handler page.
app.post('/bwp-signin-redirect/:state/:code', (req, res) => {
const sessionId = req.sessionID; // Assumes session management middleware that assigns a session ID

// ...other JavaScript code  

  if (state === storedState) {
    // ...other JavaScript code    
    // Get the LWA shopper profile
    try { 
      // Retrieve the access token saved in the previous step.     
      const accessToken = await getFromSessionDB(sessionId, 'accessToken');
      // Get shopper profile with access token.
      const shopperInfo = await getLWAShopperInfo(oAuthToken.accessToken);
      // Placeholder to store the shopper profile.
     
     } catch (error) {
        // Implement error handling here
     }
   }
});

// Get the LWA shopper profile with the LWA access token.
async function getLWAShopperInfo(accessToken) {
try {
   const response = await fetch('https://api.amazon.com/user/profile', {
      method: 'GET',
      headers: {
        'Authorization': 'Bearer ${accessToken}'
      },  
 
    if (!response.ok) {
      // Implement error handling here
    }    
    return await response.json();

   } catch (error) {
    // Implement error handling here
   } 
});

Extract information from the redirected URL

URL TypeRequired Task?
Static URLsYes
Dynamic URLsYes

After the shopper signs in, LWA redirects the shopper to the redirect_url page with an authorization code, scope, and state in the query parameters. A redirect URL looks like the following example: https://www.example.com/bwp-signin-redirect?code=example-code&state=example-state&scope=profile

Extract the code and state query parameters from the URL and validate the state to guard against cross-site request forgery (CSRF) attacks. The following example extracts the code and the state.

const urlParams = new URLSearchParams(window.location.search);
const authCode = urlParams.get('code');
const state = urlParams.get('state');

With the state extracted, you can decode the state to get the anti-forgery token and destination URL, and make sure the values match the values that you stored when you sent the authorization request.

The following code example validates the state and extracts the URL to redirect the shopper to.

Example Code That Validates the State
const express = require('express'); 
const app = express();

// Function to store data in a session management database.
async function saveToSessionDB(sessionId, data) {
  // Implement database-saving logic here.
}

// Function to get the date from a session database.
async function getFromSessionDB(sessionId, data) {
  // Your database logic to retrieve session data.
  return data_from_db; // Simulate retrieval
}

// Function to validate the redirect URL to prevent open redirects.
function validateUrl(url) {
  // Your validation logic to ensure that the URL is in your Allowed Return URLs list in LWA.
}

// The client is requesting to load the redirect handler page.
app.post('/bwp-signin-redirect/:state/:code', (req, res) => {
const state = req.params.state;
const tabId = req.tabId; // Assumes a unique tabId is generated for each tab.
const sessionId = req.sessionID; // Assumes session management middleware that assigns a session ID.  

// Get the state from the current session database.
const sessionState = await getFromSessionDB(sessionId,'sessionState');
const storedState = sessionState[tabId];

// Clear the state for the tabId in the sessionState.
delete sessionState[tabId];
await saveToSessionDB(sessionId,{'sessionState':sessionState});  

// Validate the state and get the dynamicUrl.
if (state === storedState) {
  // Decode the base64 state.
  const decodedState = Buffer.from(encodedState, 'base64').toString('utf-8');
 
  // Split the decoded state(`${forgeryKey} ${dynamicUrl}`) by spaces to get the components.
  const components = decodedState.split(' ');
  const dynamicUrl = components[1];    
 
  // We recommend that you validate the dynamicUrl to prevent open redirects.
  if (!validateUrl(dynamicUrl)){
     // Implement error handling here.
  }      
 // ...Remaining steps.
 }
});


Set up a redirect handler URL

URL TypeRequired Task?
Static URLsNo
Dynamic URLsYes

To enable dynamic redirects, you must set up a redirect handler page such as https://www.example.com/bwp-signin-redirect. Your redirect handler page manages the authentication response from Amazon and directs shoppers to destination URLs dynamically after shoppers sign in.

Your redirect handler page should do the following tasks:

  • Receive the authorization response from LWA.
  • Extract and verify query parameters, such as a code (authorization code) and state, from the redirected URL. For details, see Extract information from the redirected URL.
  • Send a request to the LWA token endpoint. The purpose of this request is to exchange the authorization code for an access token. For details, see Send an access token request.
  • Redirect the user to the dynamic URL they started from. The dynamic URL was encoded as part of the state parameter in the authorization code request.

Make sure to add your redirect handler page's URL to the Allowed Return URL of your LWA security profile.

For additional details, see Dynamically Redirect Users in the LWA documentation.


Generate and store a state

URL TypeRequired Task?
Static URLsNo but recommended
Dynamic URLsYes

Before you send an authorization request to the LWA authorization endpoint, calculate a state to put in the query parameters of the request. The state has multiple purposes:

  • For dynamic URLs, the state enables the redirect handler to record the URL of the page that the shopper was on when they clicked the sign-in link. That way, the redirect handler can redirect the shopper back to that page after authentication.
  • For both static and dynamic URLs, the state parameter can help protect against Cross-site Request Forgery (CSRF) attacks.

You can generate a state by using the URL of the page (static URL or dynamic URL) and an anti-forgery key. We recommend that you create the anti-forgery key with at least 256 bits of entropy. For details, see Calculating the State Parameter. You can concatenate the current page’s URL and the anti-forgery key, and then encode the resulting string with base-64. The following code shows how to generate a state from a URL and an anti-forgery key.

Store the state in the current session information. You must also store the anti-forgery key and the URL (static or dynamic) in the back-end session database for validation during redirection later.

Example Code to Generate a State
// Get the current page URL.  
const protocol = req.protocol;  
const host = req.hostname;  
const urlPath = req.originalUrl; 

// Includes the path and query string  
const dynamicUrl = `${protocol}://${host}${urlPath}`; 

// Generate a UUID as an anti-forgery key.  
// This is specific to CSRF handling, so it is optional if your site has other CSRF-handling mechanisms.  
const antiForgeryKey = crypto.randomUUID();  

// Generate a state with a URL and an anti-forgery key.  
// Example here is using base64 encoding, while encryption can bring further security control.  
const state = Buffer.from(`${antiForgeryKey}#${dynamicUrl}`).toString('base64');
Example Code to Store a State
// JavaScript running on the server-side (using Node.js)

// ...Other JavaScript code

// Store data in the session management database.
async function saveToSessionDB(sessionId, data) {
 // Implement database saving logic here.
}

// Get the date from the session database.
async function getFromSessionDB(sessionId, data) {
 // Your database logic to retrieve session data.
 return data_from_db; // Simulate retrieval
}

// The client is requesting to load the product detail page.
app.post('/products/:<product-id>', (req, res) => {

   // ... Other JavaScript code  
   try {
    // Get sessionState map from the session database.
    const sessionState = await getFromSessionDB(sessionId, 'sessionState')    
   
    // Store the state created in the previous step in the current session information.
    sessionState[tabId] = state;
     
    await saveToSessionDB(sessionId, { 'sessionState' : sessionState});    
   
     // Return the product detail page with the state.
    res.render('product-detail-page', { productId: productId, state: state });
   } catch (error) {
    // Implement error handling here.
   }
});

// ...other JavaScript


Add UI elements

To start the authentication flow, you must have a sign-in link on your site. If you integrate with LWA directly or you use an LWA SDK, you must create the link. If you use the Buy with Prime UI Library, the delivery card UI component displays the link for you.

Add a sign-in link

URL TypeRequired Task?
Static URLsYes
Dynamic URLsYes

If you integrate with LWA directly or by using an LWA SDK, implement your sign-in link so that it triggers a request to the LWA authorization endpoint. For details about the request, see Send an authorization request.

If you use the Buy with Prime UI library, add a delivery-card component to your UI. This component displays a sign-in link and takes care of the underlying authorization request. For examples, see Delivery Card Examples.


Add Buy with Prime UI library components to a web page

URL TypeRequired Task?
Static URLsYes, if you use the Buy with Prime UI library
Dynamic URLsYes, if you use the Buy with Prime UI library

If you integrate with LWA by using the Buy with Prime UI library, the UI library handles some of the authentication tasks for you. In particular, you don't need to send an authorization request to the LWA authorization endpoint directly. Instead, you add the delivery-card UI component to pages that you want the shopper to sign in from. The delivery card displays a sign-in link and handles the authentication flow.

When a shopper clicks the sign-in link on a delivery-card that you display on your site, the delivery card redirects them to a sign-in page through LWA. To enable this sign-in functionality, the delivery card contains an LWAConfig object to gather the necessary information from you.

After the shopper signs in, LWA redirects them to the redirectUrl that you defined in the LWAConfig. Based on your use case, you can configure LWAConfig for static redirect handling or dynamic redirect handling. In any case, don't forget to allow-list the redirectUrl in the Allowed Return URLs of your security profile. For details, see Set up an LWA Security Profile.

For details about all of the fields of the delivery-card and the LWAConfig, see the Buy with Prime UI Library Reference. For examples, see Delivery Card Examples.

The following example shows the minimum LWAConfig to generate the necessary authentication and authorization screens through redirection.

Example Code for the Minimum LWAConfig
const LWAConfig = {
 clientId: "yourLoginWithAmazonClientId",
 redirectUrl: "https://www.example.com/cart",
 signOutCallback: function() {
    // Placeholder for implementing the sign-out logic, such as clearing  
    // the shopper's state for the current session.
 }
};

The following example shows an LWAConfig that redirects the shopper back to the current page after the authorization flow.

Example Code for an LWAConfig that Redirects the Shopper to the Current Page after the Authorization Flow
const LWAConfig = {
 clientId: "yourLoginWithAmazonClientId",
 redirectUrl: windows.location.href,
 signOutCallback: function() {
    // Placeholder for implementing the sign-out logic, such as clearing  
    // the shopper's state for the current session.
 }
};

The state parameter of the LWAConfig is required for dynamic URLs. Although optional, we recommend that you provide a state for static URLs too, to prevent cross-site request forgery (CSRF). The following LWAConfig contains a state. For details about how to calculate a state, see Generate and store a state.

Example Code for an LWAConfig with a state parameter
const LWAConfig = {
 clientId: "yourLoginWithAmazonClientId",
 redirectUrl: windows.location.href,
 signOutCallback: function() {
    // Placeholder for implementing the sign-out logic, such as clearing the shopper's state for the current session 
 },
 state: "208257577ll0975l93l2l59l895857093449424"
};

LWAConfig also supports showing the authentication and authorization flow in a pop-up window rather than a redirection. To enable this flow, you must set showSignInWindowAsPopup to true . You also must add the domain of the site where the pop-up window is shown to the Allowed Origins in your security profile. The following LWAConfig uses a pop-up window.

Example Code for an LWAConfig That Uses a Pop-Up Window
const LWAConfig = {
 clientId: "yourLoginWithAmazonClientId",
 redirectUrl: "https://www.example.com/cart",
 signOutCallback: function() {
    // Placeholder for implementing the sign-out logic, such as clearing the shopper's state for the current session 
 },
 showSignInWindowAsPopup: true
};

If you integrate with LWA by using the Buy with Prime UI library, you still need to implement the access token request to the LWA token endpoint and handle redirects. For details on the tasks you need to do, see Integrate with LWA by Using Buy with Prime UI Library.


Related topics