Amazon-cognito-identity-js: Cannot read property 'Stream' of undefined

Created on 5 Jan 2017  路  12Comments  路  Source: amazon-archives/amazon-cognito-identity-js

Hi,

we are trying to move from inline script AWS files to npm packages and when trying to log in user using amazon-cognito-identity-js package, it results in this error:

TypeError: Cannot read property 'Stream' of undefined
    at Object.computeSha256 (util.js:687)
    at Request.COMPUTE_SHA256 (event_listeners.js:97)
    at Request.callListeners (sequential_executor.js:101)
    at Request.emit (sequential_executor.js:77)
    at Request.emit (request.js:668)
    at Request.transition (request.js:22)
    at AcceptorStateMachine.runTo (state_machine.js:14)
    at state_machine.js:26
    at Request.<anonymous> (request.js:38)
    at Request.<anonymous> (request.js:670)

The files from the trace are all part of this aws-sdk npm package that is a dependency of this package. The response I've got when I filed this issue there is "The error you're seeing is because the node.js version of the AWS SDK is being used instead of the browser version.".

Thanks!

bug

Most helpful comment

I see the issue is closed, but I'm still getting the same error. Is there any update on a fix?

All 12 comments

Similar question, what is the environment you are using this in and how are you getting the package? Can you make any other unauthenticated requests using the AWS SDK with no problems?

I am having a similar problem:

isArray is not a function

This also occurs during the authentication process when the library tries to calculate the SHA256 hash.

This was working without error until the last day or so.

You can see a live failure at: https://www.remotebot.io/login - note that the Cognitio library is also used on the register page as well. Please feel free to play around, @itrestian, if it helps diagnose the problem. Check out the 'AuthService' webpack module in the Chrome 'sources' view for the code that triggers the Cognitio library.

I have source maps enabled so if you follow the console error to the source you can see the line it fails on when generating the hash.

I'm also using npm with webpack to consume the Cognitio library, though I also use the AWS SDK for other things. Here's my package.json

{
  "name": "remotebot",
  "version": "0.1.0",
  "private": true,
  "devDependencies": {
    "react-scripts": "0.8.4"
  },
  "dependencies": {
    "jsbn": "^0.1.0",
    "sjcl": "^1.0.3",
    "amazon-cognito-identity-js": "^1.10.0",
    "aws-sdk": "^2.7.20",
    "flux": "^3.1.2",
    "jquery": "^3.1.1",
    "react": "^15.4.1",
    "react-dom": "^15.4.1",
    "react-modal-bootstrap": "^1.1.0",
    "react-router": "^2.0.0"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test --env=jsdom",
    "eject": "react-scripts eject",
    "deploy": "npm run build && bash ./deploy/upload-s3.sh"
  }
}

Hope this helps.

Sorry to sound melodramatic but this issue means that I am now having to evaluate whether Cognito is stable enough to use as our IDP. It's quite scary that this broke login for the site without any change occurring to the use of this code :(

We use it in browser, bundled by webpack.

package.json dependencies:

"amazon-cognito-identity-js": "^1.11.0",
"amazon-cognito-js": "^1.1.0",
"aws-sdk": "^2.7.21",

From yarn.lock:

amazon-cognito-identity-js@^1.11.0:
  version "1.11.0"
  resolved "https://registry.yarnpkg.com/amazon-cognito-identity-js/-/amazon-cognito-identity-js-1.11.0.tgz#f04f697e4cdb392c59176060a9015cc0e7859ae9"
  dependencies:
    aws-sdk "^2.6.0"
    jsbn "^0.1.0"
    sjcl "^1.0.3"

Usage:

import { CognitoUserPool, CognitoUser, AuthenticationDetails } from 'amazon-cognito-identity-js';

const poolData = {
    UserPoolId: userPoolId,
    ClientId: clientId,
};

const userPool = new CognitoUserPool(poolData);
const userData = {
    Username: username,
    Pool: userPool,
};

const user = new CognitoUser(userData);

const authData = {
    Username: email,
    Password: password,
};

const authenticationDetails = new AuthenticationDetails(authData);

user.authenticateUser(authenticationDetails, {
    onSuccess: result => {
    },
    onFailure: err => {
    },
});

Without npm packages, these are the script file names that we include to index.html and by using global AWS namespace instead of ES6 imports, everything works correctly:

<script src="/dist/src/aws/cognito/lib/jsbn.js"></script>
<script src="/dist/src/aws/cognito/lib/jsbn2.js"></script>
<script src="/dist/src/aws/cognito/lib/sjcl.js"></script>
<script src="/dist/src/aws/cognito/lib/moment.js"></script>
<script src="/dist/src/aws/cognito/lib/aws-cognito-sdk.min.js"></script>
<script src="/dist/src/aws/cognito/lib/amazon-cognito-identity-1.5.0.min.js"></script>
<script src="/dist/src/aws/cognito/lib/aws-sdk-2.5.0.min.js"></script>
<script src="/dist/src/aws/cognito/lib/amazon-cognito.min.js"></script>

So the difference here is in aws-sdk version differences: 2.5.0 -> 2.7.21 and amazon-cognito-identity 1.5.0 -> 1.11.0

@outofcoffee at first glance, by looking at the dependencies:

https://raw.githubusercontent.com/bitwiseshiftleft/sjcl/master/sjcl.js
https://github.com/andyperlitch/jsbn/blob/master/index.js

and this library

https://github.com/aws/amazon-cognito-identity-js/blob/master/dist/amazon-cognito-identity.min.js

None of the above actually uses isArray.

The only library that has isArray is the main aws-sdk which we use to make the unauthenticated calls to the service. I will further investigate but does it work if you change versions for the main aws-sdk? You also mentioned that nothing changed on your side, you didn't pick up new versions of the packages?

Thank you for looking at this, @itrestian.

Some more detail: here's the full error from the console:

index.js:378 Uncaught TypeError: re is not a function
    at Function.c.concat (index.js:378)
    at Object.digest (index.js:50)
    at Object.hash (util.js:450)
    at Object.sha256 (util.js:402)
    at Object.computeSha256 (util.js:716)
    at constructor.<anonymous> (event_listeners.js:117)
    at constructor.callListeners (sequential_executor.js:101)
    at constructor.emit (sequential_executor.js:77)
    at constructor.emitEvent (request.js:668)
    at constructor.e (request.js:22)

...and here's the corresponding function it fails in:

Buffer.concat = function concat (list, length) {
  if (!isArray(list)) {
    throw new TypeError('"list" argument must be an Array of Buffers')
  }

  if (list.length === 0) {
    return Buffer.alloc(0)
  }

  var i
  if (length === undefined) {
    length = 0
    for (i = 0; i < list.length; ++i) {
      length += list[i].length
    }
  }

  var buffer = Buffer.allocUnsafe(length)
  var pos = 0
  for (i = 0; i < list.length; ++i) {
    var buf = list[i]
    if (!Buffer.isBuffer(buf)) {
      throw new TypeError('"list" argument must be an Array of Buffers')
    }
    buf.copy(buffer, pos)
    pos += buf.length
  }
  return buffer
}

It looks to be from this project: https://github.com/feross/buffer/blob/d14a864f68f80ff1c6b591929da5d03d81af7cc5/index.js

Looks like a polyfill for Buffer :-/

The AWS SDK has the computeSha256 method in util.js here: https://github.com/aws/aws-sdk-js/blob/d0aa9db29be01cd909eec4780dffb9d182cde5e4/lib/util.js#L695

This is called from event_listeners.js here: https://github.com/aws/aws-sdk-js/blob/39c3a4704ea4c0fb23ee585fd8b703ec65b96a9a/lib/event_listeners.js#L117

Version-wise, there were updates to Buffer's use in util.js in the last month or so: https://github.com/aws/aws-sdk-js/commits/d0aa9db29be01cd909eec4780dffb9d182cde5e4/lib/util.js

The AWS SDK does depend on the npm buffer package: https://www.npmjs.com/package/buffer - looking at that project, this commit could be the culprit:

https://github.com/feross/buffer/commit/6ea2f4dc5f38022ef9b3cd8dd52db1e173c92766

remove poly fill for Array.forEach, Array.map, Array.isArray

Thank you for the analysis! @outofcoffee and @patrik-piskay.

Does your code work with previous versions of the AWS SDK (something previous to the changes observed)?

Our use of the main AWS SDK is minimal, pretty much just to make unauthenticated requests to the service which works for me when I pull the latest version.

By looking at the code, it seems that the error comes from the part of the code that calls computeSha256 to add the authentication information to the request (sig v4). That is completely unnecessary for the requests that originate from amazon-cognito-identity-js since they are all unauthenticated.

The only reason why that happens is because the signatureVersion property is for the whole service and not on an operation basis as can be seen in the service definition here https://github.com/aws/aws-sdk-js/blob/master/apis/cognito-idp-2016-04-18.min.json#L9

One temporary solution until we figure out something more permanent would be to unset this for cognito idp since it is unnecessary:

   var client1 = new AWS.CognitoIdentityServiceProvider({ apiVersion: '2016-04-19', region : 'us-east-2' });
   client1.api.signatureVersion = null;

@itrestian do we have an update for this one? Can't seem to figure out how to apply the temporary solution you've suggested for my code below.

const authenticationData = {
      Username: email,
      Password: password
    };

 const authenticationDetails = new AuthenticationDetails(authenticationData);

 const cognitoUser = new CognitoUser(userData);
 cognitoUser.authenticateUser(authenticationDetails, {
   onSuccess(result) {
        console.log(`access token + ${result.getAccessToken().getJwtToken()}`);
      },

      onFailure(err) {
        alert(err);
      }
  });

I feel so dumb, was able to add the temporary solution simply by adding the code snippet as suggested by @itrestian . I thought I needed to do something complicated. The code below now works for me.

const cognitoClient = new AWS.CognitoIdentityServiceProvider({
  apiVersion: '2016-04-19',
  region : 'us-east-2' 
});
cognitoClient.api.signatureVersion = null;

const authenticationData = {
      Username: email,
      Password: password
    };

 const authenticationDetails = new AuthenticationDetails(authenticationData);

 const cognitoUser = new CognitoUser(userData);
 cognitoUser.authenticateUser(authenticationDetails, {
   onSuccess(result) {
        console.log(`access token + ${result.getAccessToken().getJwtToken()}`);
      },

      onFailure(err) {
        alert(err);
      }
  });

@jimbocortes the above does not work for me. How does setting an unused cognitoClient help? Is that setting supposed to now be persisted for all cognito calls?

I see the issue is closed, but I'm still getting the same error. Is there any update on a fix?

@itrestian has there been a more permanent solution developed? This isn't working for me. Is there a bug in the computeSHA utility that needs to be addressed for node?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ZwaarContrast picture ZwaarContrast  路  4Comments

magnattic picture magnattic  路  5Comments

tranan89 picture tranan89  路  5Comments

kpitzen picture kpitzen  路  3Comments

syang picture syang  路  3Comments