Nevo
Nevo

Reputation: 952

Authenticating to AWS Cognito User Pool from browser JS

I am building a proof of concept web app and would like to use an AWS Cognito User Pool as my user authentication mechanism. I have configured a user pool and a client app. I have used the hosted UI to sign up a test user. Now I need to authenticate that user from the browser.

I have found two examples in AWS documentation (here and here) showing how to authenticate users against Cognito User Pools with browser-based javascript. I can't get either one to work for me.

Here's my minimum-code demonstration HTML (two textboxes and a button):

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Test Page</title>
    </head>
    <body>
        <input id="username" type="text" value="myUser"></input> <br>
        <input id="password" type="password" value="myPa55w0rd!"></input> <br>
        <button onclick="login()">Log In!</button>

        <script src="https://sdk.amazonaws.com/js/aws-sdk-2.726.0.js"></script>
        <script src="js/myscript.js"></script>
    </body>
</html>

Here's my myscript.js (version 1, from https://aws.amazon.com/blogs/mobile/accessing-your-user-pools-using-the-amazon-cognito-identity-sdk-for-javascript/):

function login() {
    AWS.config.region = "us-west-2";

    var poolData = {
        UserPoolId : 'us-west-2_redacted',
        ClientId : 'abcdefghijklmnopqrstuvwxyz'
    };
    var userPool = new AWS.CognitoIdentityServiceProvider.CognitoUserPool(poolData); <--Error here

    var authenticationData = {
        Username : document.getElementById("username").value,
        Password : document.getElementById("password").value
    };
    var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.authenticationDetails(authenticationData); 

    var userData = {
        Username : document.getElementById("username").value,
        Pool: userPool
    };
    var cognitoUser = new AmazonCognito.CognitoIdentityServiceProvider.cognitoUser(userData);

    cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: function (result) {
            var accessToken = result.getAccessToken().getJwtToken();

            /* Use the idToken for Logins Map when Federating User Pools with identity pools or when passing through an Authorization Header to an API Gateway Authorizer */
            var idToken = result.idToken.jwtToken;

            alert("Authentication successful!");
        },

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

    });
}

When I run this code, I get Uncaught TypeError: AWS.CognitoIdentityServiceProvider.CognitoUserPool is not a constructor in the line var userPool = new AWS.CognitoIdentityServiceProvider.CognitoUserPool(poolData);. Sure enough, I don't see 'CognitoUserPool' anywhere in the aws-sdk-2.726.0.js file.

Here is my second attempt, using the code example at https://docs.aws.amazon.com/cognito/latest/developerguide/authentication.html:

function login() {
    var authenticationData = {
        Username : document.getElementById("username").value,
        Password : document.getElementById("password").value
    }

    var authenticationDetails = new AmazonCognitoIdentity.authenticationDetails(authenticationData); <-- Error here
    var poolData = {
        UserPoolId : 'us-west-2_redacted',
        ClientId : 'abcdefghijklmnopqrstuvwxyz'
    };
    var userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
    var userData = {
        Username : 'username',
        Pool : userPool
    };
    var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
    cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: function (result) {
            var accessToken = result.getAccessToken().getJwtToken();

            /* Use the idToken for Logins Map when Federating User Pools with identity pools or when passing through an Authorization Header to an API Gateway Authorizer */
            var idToken = result.idToken.jwtToken;
        },

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

When I run this code, I get Uncaught ReferenceError: AmazonCognitoIdentity is not defined. Sure enough, the text 'AmazonCognitoIdentity' does not appear in the aws.sdk-2.726.0.js file.

I've been chasing my tail on this and so far haven't found a solution. I would very much like to avoid moving to the Amplify framework. That carries with it the cost of a steep learning curve for a new framework that I'd rather avoid, at least for now. In addition, I'm barely a JS programmer, and am certainly not a node programmer, so I'd have to climb the hill of learning node.js as well to make the move to Amplify.

Is it possible to authenticate a user with simple client-side Javascript, without using Amplify? If so, I'd greatly appreciate a full working example (or someone pointing out what I'm doing wrong.)

Upvotes: 2

Views: 4393

Answers (1)

Nevo
Nevo

Reputation: 952

For anyone who's coming after me with this problem, I found a solution. Whether it's the right solution or not, I don't know. Best of luck to y'all:

function login() {
    AWS.config.update({region : "us-west-2"});

    const payload = {
        AuthFlow: "USER_PASSWORD_AUTH",
        ClientId: "abcdefghijklmnopqrstuvwxyz",
        AuthParameters : {
            USERNAME: document.getElementById('username').value,
            PASSWORD: document.getElementById('password').value
        }
    }

    var cognito = new AWS.CognitoIdentityServiceProvider();
    cognito.initiateAuth(payload, function(err,data) {
        if (err) {
            alert("Error: " + err);
        }
        else {
            alert("Success!");
        }
    })
}

Upvotes: 2

Related Questions