Skip to content
This repository has been archived by the owner on Sep 27, 2023. It is now read-only.

Latest commit

 

History

History
699 lines (545 loc) · 24 KB

README.md

File metadata and controls

699 lines (545 loc) · 24 KB

Amazon Cognito Identity SDK for JavaScript

You can now use Amazon Cognito to easily add user sign-up and sign-in to your mobile and web apps. Your User Pool in Amazon Cognito is a fully managed user directory that can scale to hundreds of millions of users, so you don't have to worry about building, securing, and scaling a solution to handle user management and authentication.

We welcome developer feedback on this project. You can reach us by creating an issue on the GitHub repository or posting to the Amazon Cognito Identity forums and the below blog post:

Introduction

The Amazon Cognito Identity SDK for JavaScript allows JavaScript enabled applications to sign-up users, authenticate users, view, delete, and update user attributes within the Amazon Cognito Identity service. Other functionality includes password changes for authenticated users and initiating and completing forgot password flows for unauthenticated users.

Setup

The Amazon Cognito Identity SDK for JavaScript depends on:

  1. The CognitoIdentityServiceProvider service from the AWS SDK for JavaScript

  2. BigInteger from the JavaScript BN library

  3. The Stanford JavaScript Crypto Library

There are two ways to install the Amazon Cognito Identity SDK for JavaScript and its dependencies, depending on your project setup and experience with modern JavaScript build tools:

  • Download each JavaScript library and include them in your HTML, or

  • Install the dependencies with npm and use a bundler like webpack.

Install using seperate JavaScript files

This method is simpler and does not require additional tools, but may have worse performance due to the browser having to download multiple files.

Download each of the following JavaScript files for the required libraries and place them in your project:

  1. The Amazon Cognito AWS SDK for JavaScript, from /dist/aws-cognito-sdk.min.js

    Note that the Amazon Cognito AWS SDK for JavaScript is just a slimmed down version of the AWS Javascript SDK namespaced as AWSCognito instead of AWS. It references only the Amazon Cognito Identity service.

  2. The Amazon Cognito Identity SDK for JavaScript, from /dist/amazon-cognito-identity.min.js

  3. jsbn.js and jsbn2.js from the JavaScript BN library

  4. sjcl.js from the Stanford JavaScript Crypto Library

    Use the build from GitHub, rather than the one linked from the library's homepage, as the latter file is out-of-date and is missing required methods.

Optionally, to use other AWS services, include a build of the AWS SDK for JavaScript.

Include all of the files in your HTML page before calling any Amazon Cognito Identity SDK APIs:

    <script src="/path/to/jsbn.js"></script>
    <script src="/path/to/jsbn2.js"></script>
    <script src="/path/to/sjcl.js"></script>
    <script src="/path/to/aws-cognito-sdk.min.js"></script>
    <script src="/path/to/amazon-cognito-identity.min.js"></script>
    <script src="/path/to/aws-sdk-2.3.5.js"></script>

Using NPM and Webpack

Webpack is a popular JavaScript bundling and optimization tool, it has many configuration features that can build your source JavaScript into one or more files for distribution. The following is a quick setup guide with specific notes for using the Amazon Cognito Identity SDK for JavaScript with it, but there are many more ways it can be used, see the Webpack site, and in particular the configuration documentation

Note that webpack expects your source files to be structured as CommonJS (Node.js-style) modules (or ECMAScript 2015 modules if you are using a transpiler such as Babel.) If your project is not already using modules you may wish to use Webpack's module shimming features to ease migration.

  • Install Node.js on your development machine (this will not be needed on your server.)

  • In your project add a package.json, either use npm init or the minimal:

    {
      "private": true
    }
  • Install the required tools and dependencies into your project with npm (Node Package Manager, which is installed with Node.js):

    > npm install --save-dev webpack exports-loader source-map-loader
    > npm install --save amazon-cognito-identity-js aws-sdk jsbn sjcl
    

    These will add a node_modules directory containing these tools and dependencies into your project, you will probably want to exclude this directory from source control. Adding the --save parameters will update the package.json file with instructions on what should be installed, so you can simply call npm install without any parameters to recreate this folder later.

  • Create the configuration file for webpack, named webpack.config.js:

    • Using the included Amazon Cognito AWS SDK for JavaScript:

      // If you wish to use a custom build of the AWS SDK for JavaScript, put the relative path to it
      // here, starting with `./`, eg `./vendor/my-aws-sdk-build.js`.
      // This build must include the Cognito Identity Service Provider service.
      var AWS_SDK_BUNDLE = 'amazon-cognito-identity-js/dist/aws-cognito-sdk.min.js';
      
      module.exports = {
        // Example setup for your project:
        // The entry module that requires or imports the rest of your project.
        // Must start with `./`!
        entry: './src/entry',
        // Place output files in `./dist/my-app.js`
        output: {
          path: 'dist',
          filename: 'my-app.js'
        },
        // ... other configuration
      
        // The current version of the AWS SDK for JavaScript does not work without extra configuration
        // under webpack, see https://github.com/aws/aws-sdk-js/issues/603.
        // This configuration uses the packaged output file as it is simple, see the issue for other
        // options with different tradeoffs.
        resolve: {
          alias: {
            'aws-sdk$': AWS_SDK_BUNDLE
          }
        },
        module: {
          noParse: /aws-cognito-sdk/,
          // Optional, but makes debugging library code much nicer:
          preLoaders: [
            {
              test: /\.min\.js$/,
              loader: 'source-map'
            }
          ],
          loaders: [
            {
              test: require.resolve(AWS_SDK_BUNDLE),
              loader: 'exports?AWSCognito'
            }
          ]
        }
      };
    • Or to use the full AWS SDK for JavaScript:

      var AWS_SDK_BUNDLE = 'aws-sdk/dist/aws-sdk.min.js';
      
      module.exports = {
        // ... as before.
      
        resolve: {
          alias: {
            'aws-sdk$': AWS_SDK_BUNDLE
          }
        },
        module: {
          noParse: /aws-sdk/,
          // preLoaders: as before
          loaders: [
            {
              test: require.resolve(AWS_SDK_BUNDLE),
              loader: 'exports?AWS'
            }
          ]
        }
      };
  • Add the following into your package.json

    {
      "scripts": {
        "build": "webpack"
      }
    }
  • Build your application bundle with npm run build

Configuration

The Amazon Cognito Identity SDK for JavaScript requires three configuration values from your AWS Account in order to access your Cognito User Pool:

  • The AWS region in which the User Pool was created, e.g. us-east-1
  • The User Pool Id, e.g. us-east-1_aB12cDe34
  • A User Pool App Client Id, e.g. 7ghr5379orhbo88d52vphda6s9
    • When creating the App, the generate client secret box must be unchecked because the JavaScript SDK doesn't support apps that have a client secret.

The AWS Console for Cognito User Pools can be used to get or create these values.

If you will be using Cognito Federated Identity to provide access to your AWS resources or Cognito Sync you will also need the Id of a Cognito Identity Pool that will accept logins from the above Cognito User Pool and App, i.e. us-east-1:85156295-afa8-482c-8933-1371f8b3b145.

Usage

Use case 1. Registering a user with the application. One needs to create a CognitoUserPool object by providing a UserPoolId and a ClientId and signing up by using a username, password, attribute list, and validation data.

    AWSCognito.config.region = 'us-east-1'; //This is required to derive the endpoint
        
    var poolData = { 
        UserPoolId : '...', // Your user pool id here
        ClientId : '...' // Your client id here
    };
    var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);

    var attributeList = [];
    
    var dataEmail = {
        Name : 'email',
        Value : '[email protected]'
    };

    var dataPhoneNumber = {
        Name : 'phone_number',
        Value : '+15555555555'
    };
    var attributeEmail = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataEmail);
    var attributePhoneNumber = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataPhoneNumber);

    attributeList.push(attributeEmail);
    attributeList.push(attributePhoneNumber);

    userPool.signUp('username', 'password', attributeList, null, function(err, result){
        if (err) {
            alert(err);
            return;
        }
        cognitoUser = result.user;
        console.log('user name is ' + cognitoUser.getUsername());
    });

Use case 2. Confirming a registered, unauthenticated user using a confirmation code received via SMS.

    var poolData = {
        UserPoolId : '...', // Your user pool id here
        ClientId : '...' // Your client id here
    };

    var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
    var userData = {
        Username : 'username',
        Pool : userPool
    };

    var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
    cognitoUser.confirmRegistration('123456', true, function(err, result) {
        if (err) {
            alert(err);
            return;
        }
        console.log('call result: ' + result);
    });

Use case 3. Resending a confirmation code via SMS for confirming registration for a unauthenticated user.

    cognitoUser.resendConfirmationCode(function(err, result) {
        if (err) {
            alert(err);
            return;
        }
        console.log('call result: ' + result);
    });

Use case 4. Authenticating a user and establishing a user session with the Amazon Cognito Identity service.

    var authenticationData = {
        Username : 'username',
        Password : 'password',
    };
    var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
    var poolData = { 
        UserPoolId : '...', // Your user pool id here
        ClientId : '...' // Your client id here
    };
    var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
    var userData = {
        Username : 'username',
        Pool : userPool
    };
    var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
    cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: function (result) {
            console.log('access token + ' + result.getAccessToken().getJwtToken());

            AWS.config.credentials = new AWS.CognitoIdentityCredentials({
                IdentityPoolId : '...' // your identity pool id here
                Logins : {
                    // Change the key below according to the specific region your user pool is in.
                    'cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>' : result.getIdToken().getJwtToken()
                }
            });

            // Instantiate aws sdk service objects now that the credentials have been updated.
            // example: var s3 = new AWS.S3();

        },

        onFailure: function(err) {
            alert(err);
        },

    });

Note that if device tracking is enabled for the user pool with a setting that user opt-in is required, you need to implement an onSuccess(result, userConfirmationNecessary) callback, collect user input and call either setDeviceStatusRemembered to remember the device or setDeviceStatusNotRemembered to not remember the device.

Use case 5. Retrieve user attributes for an authenticated user.

    cognitoUser.getUserAttributes(function(err, result) {
        if (err) {
            alert(err);
            return;
        }
        for (i = 0; i < result.length; i++) {
            console.log('attribute ' + result[i].getName() + ' has value ' + result[i].getValue());
        }
    });

Use case 6. Verify user attribute for an authenticated user.

    cognitoUser.getAttributeVerificationCode('email', {
        onSuccess: function (result) {
            console.log('call result: ' + result);
        },
        onFailure: function(err) {
            alert(err);
        },
        inputVerificationCode() {
            var verificationCode = prompt('Please input verification code: ' ,'');
            cognitoUser.verifyAttribute('email', verificationCode, this);
        }
    });

Use case 7. Delete user attribute for an authenticated user.

    var attributeList = [];
    attributeList.push('nickname');

    cognitoUser.deleteAttributes(attributeList, function(err, result) {
     	if (err) {
            alert(err);
            return;
        }
        console.log('call result: ' + result);
    });

Use case 8. Update user attributes for an authenticated user.

    var attributeList = [];
    var attribute = {
        Name : 'nickname',
        Value : 'joe'
    };
    var attribute = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(attribute);
    attributeList.push(attribute);

    cognitoUser.updateAttributes(attributeList, function(err, result) {
        if (err) {
            alert(err);
            return;
        }
        console.log('call result: ' + result);
    });

Use case 9. Enabling MFA for a user on a pool that has an optional MFA setting for an authenticated user.

    cognitoUser.enableMFA(function(err, result) {
        if (err) {
            alert(err);
            return;
        }
        console.log('call result: ' + result);
    });

Use case 10. Disabling MFA for a user on a pool that has an optional MFA setting for an authenticated user.

    cognitoUser.disableMFA(function(err, result) {
        if (err) {
            alert(err);
            return;
        }
        console.log('call result: ' + result);
    });

Use case 11. Changing the current password for an authenticated user.

    cognitoUser.changePassword('oldPassword', 'newPassword', function(err, result) {
        if (err) {
            alert(err);
            return;
        }
        console.log('call result: ' + result);
    });

Use case 12. Starting and completing a forgot password flow for an unauthenticated user.

Note that the inputVerificationCode method needs to be defined but does not need to actually do anything. If you would like the user to input the confirmation code on another page, you can make inputVerificationCode call a no-op

    cognitoUser.forgotPassword({
        onSuccess: function (result) {
            console.log('call result: ' + result);
        },
        onFailure: function(err) {
            alert(err);
        },
        inputVerificationCode() {
            var verificationCode = prompt('Please input verification code ' ,'');
            var newPassword = prompt('Enter new password ' ,'');
            cognitoUser.confirmPassword(verificationCode, newPassword, this);
        }
    });

Use case 13. Deleting an authenticated user.

    cognitoUser.deleteUser(function(err, result) {
        if (err) {
           	alert(err);
            return;
        }
        console.log('call result: ' + result);
    });

Use case 14. Signing out from the application.

    cognitoUser.signOut();

Use case 15. Global signout for an authenticated user(invalidates all issued tokens).

    cognitoUser.globalSignOut();

Use case 16. Retrieving the current user from local storage.

    var data = {
        UserPoolId : '...', // Your user pool id here
        ClientId : '...' // Your client id here
    };
    var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(data);
    var cognitoUser = userPool.getCurrentUser();

    if (cognitoUser != null) {
        cognitoUser.getSession(function(err, session) {
            if (err) {
           	   alert(err);
                return;
            }
            console.log('session validity: ' + session.isValid());

            AWS.config.credentials = new AWS.CognitoIdentityCredentials({
                IdentityPoolId : '...' // your identity pool id here
                Logins : {
                    // Change the key below according to the specific region your user pool is in.
                    'cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>' : session.getIdToken().getJwtToken()
                }
            });

            // Instantiate aws sdk service objects now that the credentials have been updated.
            // example: var s3 = new AWS.S3();

        });
    }

Use case 17. Integrating User Pools with Cognito Identity.

    var cognitoUser = userPool.getCurrentUser();

    if (cognitoUser != null) {
        cognitoUser.getSession(function(err, result) {
            if (result) {
                console.log('You are now logged in.');

                // Add the User's Id Token to the Cognito credentials login map.
                AWS.config.credentials = new AWS.CognitoIdentityCredentials({
                    IdentityPoolId: 'YOUR_IDENTITY_POOL_ID',
                    Logins: {
                        'cognito-idp.<region>.amazonaws.com/<YOUR_USER_POOL_ID>': result.getIdToken().getJwtToken()
                    }
                });
            }
        });
    }
    //call refresh method in order to authenticate user and get new temp credentials
    AWS.config.credentials.refresh((error) => {
        if (error) {
            console.error(error);
        } else {
            console.log('Successfully logged!');
        }
        });

Use case 18. List all devices for an authenticated user. In this case, we need to pass a limit on the number of devices retrieved at a time and a pagination token is returned to make subsequent calls. The pagination token can be subsequently pasesed. When making the first call, the pagination token should be null.

    cognitoUser.listDevices(limit, paginationToken, {
        onSuccess: function (result) {
            console.log('call result: ' + result);
        },
        onFailure: function(err) {
            alert(err);
        }
    });

Use case 19. List information about the current device.

    cognitoUser.getDevice({
        onSuccess: function (result) {
            console.log('call result: ' + result);
        },
        onFailure: function(err) {
            alert(err);
        }
    });

Use case 20. Remember a device.

    cognitoUser.setDeviceStatusRemembered({
        onSuccess: function (result) {
            console.log('call result: ' + result);
        },
        onFailure: function(err) {
            alert(err);
        }
    });

Use case 21. Do not remember a device.

    cognitoUser.setDeviceStatusNotRemembered({
        onSuccess: function (result) {
            console.log('call result: ' + result);
        },
	onFailure: function(err) {
            alert(err);
        }
    });

Use case 22. Forget the current device.

    cognitoUser.forgetDevice({
        onSuccess: function (result) {
            console.log('call result: ' + result);
        },
        onFailure: function(err) {
            alert(err);
        }
    });

Network Configuration

The Amazon Cognito Identity JavaScript SDK will make requests to the following endpoints

For most frameworks you can whitelist the domain by whitelisting all AWS endpoints with "*.amazonaws.com".

Random numbers

In order to authenticate with the Amazon Cognito Identity Service, the client needs to generate a random number as part of the SRP protocol. Note that in some web browsers such as Internet Explorer 8, Internet Explorer 9, or versions 4.2 and 4.3 of the Android Browser, a default paranoia of 0 passed to the Stanford Javascript Crypto Library generates weak random numbers that might compromise client data. Developers should be careful when using the library in such an environment and call the sjcl.random.startCollectors() function before starting the Cognito authentication flow in order to collect entropy required for random number generation. Paranoia level should also be increased. See discussion below:

Paranoia levels can be set through the constructor:

    var poolData = {
        UserPoolId : '...', // Your user pool id here
        ClientId : '...', // Your client id here
        Paranoia : 7
    };

    var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
    var userData = {
        Username : 'username',
        Pool : userPool
    };

    var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);

or by calling the object method:

    userPool.setParanoia(7);

Change Log

Next

  • What's new

    • Nothing yet
  • What has changed

    • Removed moment.js as a dependency.

v1.1.0:

  • What has changed
    • Fixed a bug in token parsing.

v1.0.0:

  • GA release. In this GA service launch, the following new features have been added to Amazon Cognito Your User Pools.

  • Whats new

    • Webpack support.
    • Support for Custom authentication flows. Developes can implement custom authentication flows around Cognito Your User Pools. See developer documentation for details.
    • Devices support in User Pools. Users can remember devices and skip MFA verification for remebered devices.
    • Scopes to control permissions for attributes in a User Pool.
    • Configurable expiration time for refresh tokens.
    • Set custom FROM and REPLY-TO for email verification messages.
    • Search users in your pool using user attributes.
    • Global sign-out for a user.
    • Removed dependency to sjcl bytes codec.
  • What has changed

    • Authentication flow in Javascript SDK now uses Custom Authentication API
    • Two new exceptions added for the authentication APIs: These exceptions have been added to accurately represent the user state when the username is invalid and when the user is not confirmed. You will have to update your application to handle these exceptions.
      • UserNotFoundException: Returned when the username user does not exist.
      • UserNotConfirmedException: Returned when the user has not been confirmed.
      • PasswordResetRequiredException: When administator has requested for a password reset for the user.

v0.9.0:

  • Initial release. Developer preview.