Skip to main content

LWA Integration

Overview

Login with Amazon (LWA) is an approved Amazon technology to share customer data with external entities. It is based on oAuth 2.0 standard. It provides the features required from a customer perspective (customer should have the capability to view the provided consent, customer should be able to revoke the consent, business should honour the revoked consent etc). It also internally provides the required technical features: 1) Notification when the consent is revoked. 2) API to inspect the consent for a specific client and so on. Most importantly, LWA is very focused on security and abuse mitigation. LWA team actively take steps to avoid any abuse.

As part of proposed experience of Prime integration with external client, where the flow starts from Amazon App/Site and continues to client site, Prime has suggested the integration approach in this document.

Prerequisites

Client authentication can be done before/after the LWA handshake in the Online Offer Construct. More details can be found here.

Since we strongly recommend client authentication to be done after LWA handshake, there are certain prerequisites that client must follow or prepare beforehand in order to integrate with Prime and LWA. These requirements take care of all the scenarios when customer is not logged-in at the client side and LWA handshake is invoked before asking them to perform authentication at the client website/app. We are listing down all the technical requirements below required to complete this integration pattern:

  • Clients must own a data store to maintain or associate the LWA-generated token-pair to the customer’s session temporarily if customer is not logged-in already.
  • Clients may represent this association of customer’s session to the token-pair via asession-id or some unique identifier generated at their end. Clients need to keep this session-id or unique-id in browser cookies or active app/web session as well since customer is yet to login.
  • Once customer logs in, clients can link the customer identifier at their end to the token-pair and get rid of the temporary association created initially (in the first step).

LWA Integration - Steps

A client is supposed to first complete the standard LWA on-boarding process through LWA public portal. Client will do following steps:

  1. Sign up for account to access LWA, through LWA public portal - https://developer.amazon.com/docs/login-with-amazon/register-web.html
  2. After the signup process, client will get LWA ApplicationId and LWA secret key. Please store the key in a secure location.

After the sign up process is done, client can start the LWA screen integration in their flow. In this section, we list the important aspects that client should keep in mind as part of “LWA screen” integration.

1. Touchless Flow

The scope of this section is to establish a general SOP for the clients, who wish to create an auto-redirect to LWA page from their page in the browser flow. Client’s mobile app will also initiate the LWA handshake flow in the browser. Steps are as follows:

  • Implement Auto-Redirect from client page to LWA consent/ sign up page

    • Add the following code after the opening <body> in your page to load the Login with Amazon SDK for JavaScript, and the <amazon-root> tag, into your page.

      <div id="amazon-root"></div>

      <script type="text/javascript">

      window.onAmazonLoginReady = function() {
      amazon.Login.setClientId('YOUR-CLIENT-ID');
      return false;
      }

      (function(d) {
      var a = d.createElement('script');
      a.type = 'text/javascript';
      a.async = true;
      a.id = 'amazon-login-sdk';
      a.src = 'https://assets.loginwithamazon.com/sdk/na/login1.js';
      d.getElementById('amazon-root').appendChild(a);
      })(document);

      </script>
    • After the SDK has loaded, it will call window.onAmazonLoginReady for initialization. Before using the SDK, you must call amazon.Login.setClientId` passing your client identifier.

    • Replace YOUR-CLIENT-ID with the Client ID generated when you Registered Your Application.

    • Add the following JavaScript function on your site to return an AuthorizeRequest object. This function will be called when window.onAmazonLoginReady is invoked that is after the SDK gets Loaded. After the request is complete, the object will contain properties detailing the response (such as an access token or authorization code, which you can use to obtain customer profile information):

      <script type="text/javascript">
      function lwa() {
      options = {};
      options.scope = 'SCOPE';
      options.pkce = true;
      options.popup = false;
      amazon.Login.authorize(options, "REDIRECT-URL");
      };
      </script>
    • Replace SCOPE with the LWA scopes for which you want customer’s consent.

      • You need to pass a profile scope. If you only need customer unique amazonid then just use profile:user_id scope. The profile has more scopes to get customer name and email-id too. Please do note, if you add more scopes then the corresponding messaging will be shown on consent screen. For example, if you want customer name then the consent screen will show this message also “You consent to share your user name”. Our recommendation is to only use the profile scope which provides the needed data. List of all profile scopes - https://developer.amazon.com/docs/login-with-amazon/customer-profile.html

      • For Prime benefit status, the client needs to pass the additional scope name. Prime benefit scope name is prime:benefit_status. The absence of this scope means that consent page will not show message “Your Prime status”. However, we will be able to test the complete LWA flow end to end.

      • Since the client needs to pass multiple scopes (profile and prime scope), they can pass multiple scopes through this method: You can pass multiple scopes by space separation like this: scope=profile%20prime%3Abenefit_status (space gets converted to "%20" and ":" to "%3A" in URL Encoding, reference - link)

      options.scope = 'profile prime:benefit_status';
      options.scope_data = {
      'profile' : {'essential': true},
      'prime:benefit_status' : {'essential': true}
      };
    • Replace REDIRECT-URL with the url where you want to take the customer after the completion of LWA consent flow.

2. State param

When interacting with Login with Amazon(LWA), state param is an opaque value used by the client to maintain state between the request and the response. Client will create the unique (one time use) value per request and pass it as queryParam when invoking LWA authorization endpoint. At the end of LWA flow, LWA will include this value when redirecting the user back to the client. Client have to assure that the value passed in request and received in response are the same.

This is required to prevent various risks like “Remote account takeover risk”. More details are in Appendix A.

How do client generate the state param?

Clients can calculate the state parameter value in any way they choose, however, the value should be secure from forgery. LWA provided recommendation for creating state param is available in https://developer.amazon.com/docs/login-with-amazon/cross-site-request-forgery.html#calculating-the-state-parameter

LWA recommendation is to generate the state param on the server side and persisted along with setting the browser cookie. In above sequence diagram, the state param should be generated when the server gets the call to render the client page (with touch-less LWA). In response server should provide the page content along with the cookies holding state param.

How do client use the state param?

Client should generate the unique state param value per request. Client should also associate that state param on their server side to cookies in the browser. When invoking LWA authorization endpoint the state param should be passed as queryParam. In LWA response, client should validate if the state param value in response is same as in browser cookies.

This will also detect if the url is played from another browser.

3. Backend Integration

After the signup process is done, clients can start the LWA backend integration with their flow for:

  • Generating the tokenPair (accessToken and refreshToken) from the authCode.
  • Generating the accessToken from refreshToken for subsequent calls.

Following section provides details of the backend integrations required as part of the CX. For a detailed documentation on LWA, please refer - https://developer.amazon.com/docs/login-with-amazon/documentation-overview.html

3.1 Access Token Request using Auth Code

LWA public documentation link - https://developer.amazon.com/docs/login-with-amazon/authorization-code-grant.html#access-token-request

After clients receives the authorization code, they should use that code to obtain an access token by calling LWA APIs. With an access token, the client can read a customer profile.

To request an access token, the client makes a secure HTTP POST request to one of the following regional endpoints:

Note: Applications are not region-specific. You can create, verify, and refresh tokens using any regional LWA endpoint, regardless of the region the application is created, the region of the customer or the region in which the token is created. Use the parameters listed in the table below for your POST request.

ParameterDescription
grant_typeREQUIRED. The type of access grant requested. Must be Authorization_code.
codeREQUIRED. The auth code obtained.
redirect_uriREQUIRED. The redirect URL.
client_idREQUIRED. The client identifier. This is set when you register your website as a client. For more information, see Client Identifier - https://developer.amazon.com/docs/login-with-amazon/security-profile.html#client-identifier
client_secretRECOMMENDED. The secret value assigned to the client during registration. We recommend this as it provide an option to get the long lived refreshToken as well which will help in minimizing the friction for customer’s subsequent visit. When no client_secret is passed, no refresh token will be returned. Access token will still be returned if the code_verifier is valid.
code_verifierRECOMMENDED. The same code_verifier that was used to generate the code_challenge in the Authorization Request. Required if code_challenge was used in the authorization request. For more information, see the PKCE RFC.

3.2 Access Token Response

When clients makes a secure HTTP POST Authorization Request to LWA, the authorization server immediately returns an access token or an error in the HTTP response. For example,

HTTP/1.1 200 OK
Content-Type: application/json;charset UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"Atza|IQEBLjAsAhRmHjNgHpi0U-Dme37rR6CuUpSR...",
"token_type":"bearer",
"expires_in":3600,
"refresh_token":"Atzr|IQEBLzAtAhRPpMJxdwVz2Nn6f2y-tpJX2DeX..."
}

A successful response includes the following values:

ParameterDescription
access_tokenThe access token for the user account. Maximum size of 2048 bytes.
token_typeThe type of token returned. Should be bearer.
expires_inThe number of seconds before the access token becomes invalid.
refresh_tokenA refresh token that can be used to request a new access token. Maximum size of 2048 bytes - https://developer.amazon.com/docs/login-with-amazon/refresh-token.html

Response parameters are encoded using the application/json media type. For more information, see RFC4627.

3.3 Access Token Errors

For some errors, the authorization service may return an HTTP 401 (Unauthorized) status code. This includes cases where the client passed the client_id and client_secret values in the Authorization header and the client could not be authenticated. An unsuccessful response includes the following values:

Error ParameterDescription
errorAn ASCII error code with an error code value.
error_descriptionA human-readable ASCII string with information about the error, useful for client developers.
error_uriA URI to a web page with human-readable information about the error, useful for client developers.

The following error codes can be returned as the value for error:

Error CodeDescription
invalid_requestThe request is missing a required parameter, has an invalid value, or is otherwise improperly formed.
invalid_clientThe client authentication failed. This is used in cases when the authorization service does not return an HTTP 401 (Unauthorized) status code.
invalid_grantThe authorization code is invalid, expired, revoked, or was issued to a different client_id.
unauthorized_clientThe client is not authorized to use authorization codes. Can be caused by invalid code_verifier.
unsupported_grant_typeThe client specified the wrong token_type.
ServerErrorThe server encountered a runtime error.

3.4 Access Token Request Using Refresh Token

Access tokens will expire after a set time period (normally returned in the expires_in parameter). When you obtain an access token, you will also receive a refresh token. You can use a refresh token to retrieve a new access token. To submit a refresh token, the client makes a secure HTTP POST to https://api.amazon.com/auth/o2/token with the following parameters:

ParameterDescription
grant_typeREQUIRED. The type of access grant requested. Must be refresh_token.
refresh_tokenREQUIRED. The refresh token returned by the original Access Token Response (described above).

For example,

POST /auth/o2/token HTTP/1.1
Host: api.amazon.com (http://api.amazon.com/)
Content-Type: application/x-www-form-urlencoded;charset=UTF-8

grant_type=refresh_token
&refresh_token=Atzr|IQEBLzAtAhRPpMJxdwVz2Nn6f2y-tpJX2DeX...
&client_id=foodev
&client_secret=Y76SDl2F

Note: The client_id and client_secret may be passed in the Authorization header instead, using HTTP Basic authentication. For more information, see RFC2617. For example,

POST /auth/o2/token HTTP/1.1
Host: api.amazon.com (http://api.amazon.com/)
Authorization: Basic czzCaGRSa3F0MzpnWDFmQmF0M2JW
Content-Type: application/x-www-form-urlencoded;charset=UTF-8

grant_type=refresh_token
&refresh_token=Atzr|IQEBLzAtAhRPpMJxdwVz2Nn6f2y-tpJX2DeX...

The response to a refresh token submission is an Access Token Response.

Sample code for LWA integration at client side

Sample code for touch-less LWA invocation page:

<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

<body onload = "lwa()">
<div id="amazon-root"></div>
</body>

<script type="text/javascript">
window.onAmazonLoginReady = function() {
amazon.Login.setClientId('YOUR-CLIENT-ID');
};

(function(d) {
var a = d.createElement('script');
a.type = 'text/javascript';
a.async = true;
a.id = 'amazon-login-sdk';
a.src = 'https://assets.loginwithamazon.com/sdk/na/login1.js';
d.getElementById('amazon-root').appendChild(a);
})(document);

function lwa() {
options = {};
options.scope = 'SCOPE';
options.pkce = true;
options.popup = false;
amazon.Login.authorize(options, "REDIRECT-URL");
};
</script>

Appendix A - Account Take Over Risk

In this an attacker will be able to take control of victim account on client site.

Lets see one of the scenario how this could be done: Attacker's browser steps:

  1. Attacker starts LWA flow and sign-in with his account.
  2. LWA generates auth_code
  3. LWA redirects to 3PClient.com/return_url?auth_code=AMZ123. (Attacker blocks this request on their browser)
  4. Attacker copies that URL and shares it with the victim with different messaging.

Victim's browser steps:

  1. Victim is already signed in to website 3PClient.com with 3P_CID_vic
  2. Click's the attacker's link: 3PClient.com/return_url?auth_code=AMZ123
  3. On clicking the link, attackers Amazon tokens(AMZ123's) and Amazon directed id, gets linked to victim's 3P account 3P_CID_vic.

Though this happens only if 3P Client supports “Login with Amazon” on their site and also if 3P Client use reverse mapping to link 3P account to Amazon account. In such case an attacker will login through “Login with Amazon” and will be able to get access to 3P account(as attacker’s Amazon account is already linked to the victim’s 3P account).

To avoid this risk, client have to use state param as explained in the section State param.

Appendix B - Security constraints to be followed by clients

Prime looked at multiple security steps that needs to be taken (and are prescribed for OAuth 2.0 standard). We list below the various security steps that the integration should adhere to:

  1. Authorization code take over attack

    • When the authorization code is passed b/w apps then a malicious app can also get the authorization code (more details on why this happen is out of the context of this document).
    • A malicious app should not be able to use the authorization code to generate the token. To prevent this, client needs to make sure that LWA secret key (used to exchange authorization code with token) is not leaked externally. The logic to convert auth code to token-pair should only happen at server side.
  2. CSRF attack

    • We have looked at every page in the integration to ensure that no unwanted side-effects can happen when customer is made to land directly there. We have covered all the pages except the 3P set of pages.
    • We are expecting that 3P will also have the CSRF protection on activation page.
  3. Account take over attack

    • LWA is an open technology which can also be used by external clients for authenticating their customers (in addition to it being used for data sharing).
    • An attacker can generate the final redirect link of LWA by going through the whole flow. An attacker can give this link to the victim with different messaging. When victim clicks on the link, the victim can go through the 3P activation flow without realizing that the Amazon account linked is of Attacker.
    • In itself, it doesn’t pose any immediate danger. However, if the client is also using LWA for “login purpose” then the Amazon account linking (in point b above) can result in Attacker being able to log-in to 3P account of victim with Amazon credentials. This would require fair amount of work on client side to prevent it.
  4. Token pair management

    • Token pair should ideally be not kept in the HTML of the page. It is preferable that it should be only kept at the server side. The token pair from browser HTML could be leaked by malicious scripts.