Using the AWS JavaScript SDK in the Browser

by Saad Mousliki on April 28, 2014

The modern web is always changing, and this article is more than two years old.

By Saad Mousliki

Amazon is the market leader of Cloud services, offering a huge range of services, currently 27 services. Those services are accessed via a web management console, which is a web application that allows the management of the AWS services using a rich and interactive UI. Amazon also provide a set of APIs using REST/JSON or SOAP/XML that give developers the ability to automate tasks and supervise consumed services by using their programming of choice: Java, C#, PHP, Python, JavaScript Server Side via NodeJS or Wakanda and many others.

However, the JavaScript SDK offered by Amazon was unusable in the browser, due to the security weakness related to the use of credentials (AWS_ClientID and AWS_SecretKey) in the browser to authenticate and sign all queries to the consumed AWS services. Those credentials could be reused by any application user to consume the same services, allowing them to enjoy free services. Therefore this SDK was limited only to server side using NodeJS, Wakanda or any other SSJS engine (Server Side JavaScript).

At the end of 2013 Amazon provided the ability for client-side JavaScript developers to create web applications without the need to have a backend server or to configure an application server for hosting. This new SDK solves the security weakness of the old SDK using the AWS IAM Service (AWS Identity and Access Management) with the authentication providers Facebook, Google Identity Federation, and Amazon. More details about this part will be given in the following section.

In this article, I will introduce this new architecture and explain the step-by-step workflow to prepare the environment and consume one of the AWS services from a browser-based app.

The New AWS JS SDK Architecture

As mentioned in the introduction, using the new JavaScript SDK in the browser, a web app could be developed without any need to a server side backend.

The new, two-tier architecture contains a third party, the Web Identity Federation, where the application user will authenticate and, after that, provides an access token to the user. It can be considered as a Kerberos Server, whereby the architecture and workflow will be as follows :

newArchitecture

The old, three-tiered architecture used the server-side back-end code to authenticate the user and sign all the requests to AWS services by the AWS account credentials (AWS_ClientID and AWS_SecretKey). It did not use a temporary access token, so the new architecture could be considered more secure than the old one, due to the fact that the credentials are not used within the whole app code.

The 3 Parts of the New Architecture

  • The Web Application: A client side (HTML, JavaScript, and CSS) web application that integrates the AWS-SDK and has a login dialog to authenticate and send credentials to the Web Identity Federation.
  • The Web Identity Federation: A third part that will be registered in Amazon IAM service as a trusted access provider, and that is used to authenticate the web application users via the OAuth 2.0 protocol to provide a temporary access token for consuming the AWS services.
  • AWS Services: The set of predefined services that can be consumed by the web application, those settings are defined in the IAM service. The 5 services that come with the default JS SDK in the browser are:
    1. AWS DynamoDB: A NoSQL database service that allows scalability and many other features.
    2. AWS.SNS: A Simple Notification Service that allows push notifications.
    3. AWS.SQS: A Simple Queue Service that allows the creation and management of queues.
    4. AWS.S3: The Simple Storage Service that allows object storage and management, one of the most used services.
    5. AWS.S3: A Security Token Service that provides a temporary access token.

How to use the new AWS JS SDK

Before we start writing any code, we first need to prepare and configure the environment by creating an app ID in the Web Identity Federation side, create a role, configure permissions for this role in the AWS IAM side console, and assign the app Client ID to the created role to establish the connection between the two parts:

Create a Google App ID

To create a Google app and get the app ID that should be used in AWS IAM side, we need to log in to Google APIs, click on Create Project button, fill the project name and check the agreement checkbox.

After creating a Google project, click on the project name to open the project console :

Google Console

Click on APIs an auth item in the left menu and activate the Google+ API by clicking on the OFF button, then agree by checking the agreement checkbox:

GPlusActivate

Once we’ve finished the Google+ API activation, we need to get the app’s client ID. Go to the Credentials item in the left menu and create a new client ID for web application. In the authorized JavaScript origin set the name of your computer along with the port number, e.g. http://PC.saadMousliki:9090 :

GClientID

Download the JSON file for the created client ID and save it to be used in the AWS IAM console, for more details take a look to this doc.

Create an AWS IAM Role

After finishing the configuration in the Web Identity Federation console, let’s switch to the AWS IAM management console. We’ll start by creating a new role that will set the AWS services’ permission for our app.

Open the IAM console here, go to the left menu, click on Roles item and click on Create new role button to start the the creation steps. Once this is complete, click on Role for Identity Provider Access radio button :

IAMRole

Next, select the identity provider from the drop down list and enter the client ID in the audience text input and click on continue:

SetIdentityProvider

We can edit the policy JSON doc to set the app permissions on the AWS services. Take a look to this doc for more details.

We can edit the permissions document manually or by using the policy generator and entering the Amazon Resource Name (ARN):

policyGen

Now, Click on Create Role button to close the role creation wizard.

The environment preparation and configuration has finished now, it’s a long and not trivial process, but it consolidates the app security. If we compare it with the configuration and deployment of a web app with a backend server, it could be considered a time and money saving process.

Load the SDK in the Browser

We’re now ready start the development of the app which will use the already prepared environment. First, we need to create the HTML page that will use the AWS JS SDK. To load the SDK in the browser, we simply need to add the following script tag:

<script src="https://sdk.amazonaws.com/js/aws-sdk-2.0.0-rc13.min.js"></script>

You should know that the SDK is distributed under the Apache License, Version 2.0

Get the Access Token from the WIF

When a web user signs in using his Google credentials, we should call the Web Identity provider which we configured earlier (using the Google+ API) to get the temporary access token to the AWS services which represents the authenticated web user to Amazon. To allow this we should load the Google+ API that will be used to send the request to the WIF by adding the following script tag :

<script src=" https://apis.google.com/js/client:plusone.js?onload=init"> </script>

We see that an onload property is added to the source which is used to execute a callback function, init, after that the Google+ API is properly loaded. In our init function we will load the Google+ API to authenticate the web users oAuth2 :

function init(){

/* Load the OAUTH2 Google API */
gapi.client.load('oauth2', 'v2', function() {

  getAccessToken();

});
}

The code is already documented, but I should add that if you have used the V1 version of the Google+ API, you should replace the ‘v2’ argument of load method by ‘v1’.

The getAccessToken() function will use the following code to authenticate the web user and get a temporary access to AWS services:

function getAccessToken(){
  var request = gapi.client.oauth2.userinfo.get();
  request.execute(function{resp}{
       serviceUser = resp;
  });
}

The serviceUser object should be declared at the top of the page. It’s the object that will contain the user email, the access token and other properties. This object will be used afterwards to authenticate the user in the AWS service.

For more details, take a look at how to add Google+ sign in to your page.

Use the JS AWS SDK

After having the temporary credentials (access token) from the Web Identity Federation (Google+ in our example) we should be able to call any AWS Services that is supported by the SDK from the five services listed earlier the article.

To authenticate our application on the AWS side, we should use the ARN (Amazon Resource Name) that we have received when preparing the environment, and the serviceUser variable that we filled in the previous section.

We use the JS AWS SDK the same way as it used when working with the AWS SDK for Server Side JavaScript. The SDK keeps the same methods and properties, making the code migration very simple from server side to client side. Let’s look at a code example of how to use the SDK:

// First set the region for the AWS SDK

AWS.config.region = 'us-west-2';

// second prepare the config object

var myArn = "arn:aws:iam::[ACCOUNT_ID]:role/google-web-role";
var myAccessToken = serviceUser.id_token;

var awsConfig = {
      RoleArn : myArn,
      WebIdentityToken : myAccessToken,
      RoleSessionName : 'web'

};

// and configure the AWS credentials
AWS.config.credentials = new AWS.WebIdentityCredentials(awsConfig);

For more details about how to create the web identity credentials, take a look at this AWS doc.

Finally, and after preparing the environment and configuring the web identity credentials, we can now load the AWS services objects and consume the services from our app. As an example, let’s load the AWS S3 object to access a specific bucket and show the web user the number of objects in this bucket:

var myBucket = new AWS.S3({params: {Bucket : 'bucket_Name'}});
 
myBucket.listObjects(function (error, data){

     if(error){
        alert('problem when loading the S3 buckets objects');
               }
     else{
   alert('you have ' + data.Contents.length + ' objects on you bucket');
         }
  
});

Many code snippets showing how to use the JS AWS SDK can be found on this Amazon official guide.

Conclusion

This new AWS SDK can completely change the way we develop web or mobile apps, giving more flexibility to front end developers who no longer have to write server side code. Hopefully this article was able to introduce you to the SDK if who haven’t yet used it and gave you the steps needed to use it, which, as you can see, are not trivial.