aws-amplify / amplify-js

A declarative JavaScript library for application development using cloud services.
https://docs.amplify.aws/lib/q/platform/js
Apache License 2.0
9.36k stars 2.1k forks source link

Error: Native crypto module could not be used to get secure random number. #7098

Closed Benzer1406 closed 3 years ago

Benzer1406 commented 3 years ago

Describe the bug I'm using the serverless.com framework together with: "amazon-cognito-identity-js": "^4.5.2" and I still get the error: Error: Native crypto module could not be used to get secure random number. even though it was supposed to be fixed in version 3.2.0.

It happens when I use the CognitoUser.authenticateUser method. Any updates on this issue?

amhinson commented 3 years ago

@Benzer1406 Are you still experiencing this issue after using the unstable tag and setting global.crypto = require('crypto'), as we discussed in the other issue? https://github.com/aws-amplify/amplify-js/issues/4886#issuecomment-720102849

Benzer1406 commented 3 years ago

@amhinson No, that solved it for me. If you want to you can close the issue when you released the fix on the stable version, leaving a comment here to let everybody know.

amhinson commented 3 years ago

Ok will do. Thanks for the follow up! I will update the issue once it is released to latest.

For anyone seeing the same issue using Node, you can get around it by using amazon-cognito-identity-js@unstable and/or aws-amplify@unstable and setting global.crypto = require('crypto') at the top of the file before any imports.

manojkumarg16 commented 3 years ago

@amhinson I used unstable tag for amazon-cognito-identity-js and crypto on top of all the imports as mentioned in earlier comments, Still issue remains same.

Error: Native crypto module could not be used to get secure random number.

amhinson commented 3 years ago

@manojkumarg16 Could you provide some more details so I can try to reproduce the issue you're seeing? A code snippet of the file you're working with would help.

manojkumarg16 commented 3 years ago

@amhinson Here is the code, a simple function const globalAny:any = global; globalAny.fetch = require('node-fetch'); globalAny.crypto = require('crypto'); const AmazonCognitoIdentity = require('amazon-cognito-identity-js');

const login = (email_id, pass) => { / Login / const authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails({ Username : , Password : , }); return new Promise((resolve,reject) => { cognitoUser.authenticateUser(authenticationDetails, { onSuccess: (result) => { resolve(result); }, onFailure: (err) => { reject(err); } }); }) }

}

amhinson commented 3 years ago

Can you try assigning require('crypto') directly to global.crypto instead of globalAny.crypto? Here's where we're using it in the amazon-cognito-identity-js code: https://github.com/aws-amplify/amplify-js/blob/main/packages/amazon-cognito-identity-js/src/utils/cryptoSecureRandomInt.js#L15

amhinson commented 3 years ago

Also, what version of Node are you using?

manojkumarg16 commented 3 years ago

@amhinson I'm using typescript , so type need to be denoted, that's the reason I used it as globalAny:any = global. as mentioned here : https://github.com/aws-amplify/amplify-js/issues/4886#issuecomment-720101857

I'm using node v12.18.3

amhinson commented 3 years ago

Could you try doing that anyway, perhaps just with a // @ts-ignore for now just to validate if it changes anything?

Also, can you also delete your node_modules and yarn.lock/package-lock.json and install the dependencies again?

manojkumarg16 commented 3 years ago

@amhinson tried as you said, but nothing turned up. Still issue remains

amhinson commented 3 years ago

Can you share your package.json?

manojkumarg16 commented 3 years ago

{ "name": "serverless", "version": "1.0.0", "main": "index.js", "license": "MIT", "scripts": { "start": "env-cmd -f .env.dev nodemon --exec serverless offline start --httpPort 4000 --websocketPort 4001 --lambdaPort 4002", "package": "SLS_DEBUG= sls package", "deploy-function": "SLS_DEBUG= sls deploy function --function graphql", "deploy-stack": "SLS_DEBUG=* sls deploy", "prisma:generate": "prisma generate", "prisma:introspect": "prisma introspect", "lint": "eslint ." }, "dependencies": { "@prisma/client": "^2.6.2", "@types/graphql-fields": "^1.3.3", "amazon-cognito-identity-js": "^4.5.3-unstable.1", "apollo-errors": "^1.9.0", "apollo-server": "^2.19.0", "apollo-server-express": "2.17.0", "aws-sdk": "^2.4.8", "class-validator": "^0.12.2", "crypto-js": "^3.3.0", "eslint-import-resolver-webpack": "^0.12.2", "express": "^4.17.1", "graphql": "^15.3.0", "graphql-fields": "^2.0.3", "graphql-middleware-sentry": "^3.2.1", "graphql-playground-middleware-express": "1.7.20", "graphql-tag": "2.11.0", "graphql-tools": "6.2.1", "graphql-type-json": "^0.3.2", "jsonwebtoken": "^8.5.1", "jwk-to-pem": "^2.0.4", "nexmo": "^2.9.1", "node-fetch": "^2.6.1", "nodemailer": "^6.4.13", "otp-generator": "^2.0.0", "password-generator": "^2.3.2", "path": "^0.12.7", "pg": "^8.3.3", "reflect-metadata": "^0.1.13", "request": "^2.88.2", "serverless-http": "^2.5.0", "source-map-support": "^0.5.19", "telesignsdk": "^2.2.1", "type-graphql": "^1.0.0" }, "devDependencies": { "@prisma/cli": "^2.6.2", "@types/express": "^4.17.8", "@types/jest": "26.0.13", "@types/node": "14.6.4", "@types/nodemailer": "^6.4.0", "@typescript-eslint/eslint-plugin": "2.24.0", "@typescript-eslint/parser": "2.30.0", "copy-webpack-plugin": "^6.1.0", "cors": "2.8.4", "env-cmd": "10.1.0", "eslint": "6.8.0", "eslint-config-airbnb": "18.1.0", "eslint-config-airbnb-typescript": "7.2.1", "eslint-config-prettier": "6.10.0", "eslint-plugin-import": "2.20.1", "eslint-plugin-jest": "23.8.2", "eslint-plugin-jsx-a11y": "6.2.3", "eslint-plugin-prettier": "3.1.2", "husky": "4.2.5", "jest": "25.2.2", "lint-staged": "10.0.8", "nodemon": "^2.0.4", "prettier": "1.19.1", "serverless": "1.78.0", "serverless-dotenv-plugin": "^3.0.0", "serverless-offline": "6.5.0", "serverless-webpack": "5.3.3", "ts-loader": "^8.0.3", "typegraphql-prisma": "^0.6.0", "typescript": "3.8.3", "webpack": "4.42.0", "webpack-node-externals": "2.5.2" } }

amhinson commented 3 years ago

I'm having some trouble trying to replicate the issue you're seeing unfortunately 😕 . I just created a new Serverless framework Express app using some of the same code snippets you provided and I am able to successfully authenticate a user. Would you be able to look into creating a basic Express app that you could share with me to show the behavior you're seeing, and then provide some reproduction steps?

manojkumarg16 commented 3 years ago

Week back I wrote a rough code snippet of same which was working fine. Now I just reused the snippet which is throwing error, quite strange :(

amhinson commented 3 years ago

@Benzer1406 This fix is now available with latest 👍

@manojkumarg16 Can you try with the latest version to see if any behavior changes?

manojkumarg16 commented 3 years ago

@amhinson tried with latest version of crypto , still issue persists "amazon-cognito-identity-js": "^4.5.3-unstable.1", "crypto-js": "^4.0.0",

manojkumarg16 commented 3 years ago

@amhinson It started working after downgrading amazon-cognito-identity-js from ^4.5.3-unstable.1--> 4.5.0 and removing crypto-js . Thanks for your support @amhinson

amhinson commented 3 years ago

@manojkumarg16 can you try with "amazon-cognito-identity-js": "4.5.3"? You also shouldn't need to install crypto-js unless you're using it explicitly in your project.

pathiyilnaveen commented 3 years ago

@amhinson I tried with "amazon-cognito-identity-js": "4.5.3" I am still getting the same issue .

amhinson commented 3 years ago

@pathiyilnaveen Could you share your code or a small reproducible example so we can try to replicate the issue you are seeing?

pathiyilnaveen commented 3 years ago

I am using amplify on my unit tests @amhinson

const chai = require('chai');
const chaiHttp = require('chai-http');
const mocha = require('mocha');
const Amplify = require('aws-amplify');
const { Auth } = require('aws-amplify');

const { describe, before } = mocha;
const { it } = mocha;
const { expect } = require('chai');

chai.use(chaiHttp);
chai.should();

Amplify.default.configure({
  Auth: {
    // REQUIRED - Amazon Cognito Identity Pool ID
    identityPoolId: 'ID_POOL_ID',
    // REQUIRED - Amazon Cognito Region
    region: 'us-east-1',
    // OPTIONAL - Amazon Cognito User Pool ID
    userPoolId: 'USR_POOL_ID',
    // OPTIONAL - Amazon Cognito Web Client ID
    userPoolWebClientId: 'WEB_CLIENT
  },
});

async function onUserSignIn(email, password) {
  const username = email;
  await Auth.signIn(username, password).then((user) => {
    global.cognito_id = user.username;
  });
}

before(async function () {
  this.timeout(10000);
  const mailId = 'test@gmail.com';
  const password = 'test@123';
  await onUserSignIn(mailId, password);
});

Below is my dependencies in package.json

"dependencies": { "@babel/cli": "^7.10.1", "@babel/preset-env": "^7.10.2", "amazon-cognito-identity-js": "4.5.3", "aws-amplify": "^3.0.23", "aws-sdk": "^2.756.0", "axios": "^0.20.0", "body-parser": "^1.19.0", "bull": "^3.14.0", "bull-board": "^0.9.0", "casbin": "^5.0.4", "casbin-sequelize-adapter": "^2.1.0", "chai": "^4.2.0", "chai-http": "^4.3.0", "cookie-parser": "~1.4.4", "cors": "^2.8.5", "cpx": "^1.5.0", "cross-fetch": "^3.0.5", "debug": "~2.6.9", "elasticsearch": "^16.7.1", "express": "~4.16.1", "express-validator": "^6.6.0", "geoip-lite": "^1.4.2", "http-aws-es": "^6.0.0", "ioredis": "^4.17.3", "json-rules-engine": "^5.0.3", "jsonwebtoken": "^8.5.1", "jwk-to-pem": "^2.0.3", "lodash": "^4.17.19", "logform": "^2.2.0", "mocha": "^7.2.0", "moment": "^2.29.1", "morgan": "~1.9.1", "multer": "^1.4.2", "nodemailer": "^6.4.8", "nodemon": "^2.0.4", "npm-run-all": "^4.1.5", "pg": "^8.2.1", "pg-hstore": "^2.3.3", "read-excel-file": "^4.0.6", "redis": "^3.0.2", "redis-clustr": "^1.7.0", "rimraf": "^3.0.2", "save": "^2.4.0", "save-dev": "0.0.1-security", "sequelize": "^5.21.12", "swagger-jsdoc": "^4.2.0", "swagger-stats": "^0.95.18", "swagger-ui-express": "^4.1.4", "winston": "^3.3.3", "winston-daily-rotate-file": "^4.5.0", "xlsx": "^0.16.7" },

here is the error i get 1) "before all" hook in "{root}"

0 passing (13ms) 1 failing

1) "before all" hook in "{root}": Error: Native crypto module could not be used to get secure random number. at cryptoSecureRandomInt (node_modules/amazon-cognito-identity-js/lib/utils/cryptoSecureRandomInt.js:43:9) at WordArray.random (node_modules/amazon-cognito-identity-js/lib/utils/WordArray.js:50:56) at randomBytes (node_modules/amazon-cognito-identity-js/lib/AuthenticationHelper.js:40:58) at AuthenticationHelper.generateRandomSmallA (node_modules/amazon-cognito-identity-js/lib/AuthenticationHelper.js:101:21) at new AuthenticationHelper (node_modules/amazon-cognito-identity-js/lib/AuthenticationHelper.js:56:29) at CognitoUser.authenticateUserDefaultAuth (node_modules/amazon-cognito-identity-js/lib/CognitoUser.js:264:32) at CognitoUser.authenticateUser (node_modules/amazon-cognito-identity-js/lib/CognitoUser.js:237:19) at /smart-property/service-api/service-api/service-api/node_modules/@aws-amplify/auth/lib/Auth.js:515:18 at new Promise () at AuthClass.signInWithPassword (node_modules/@aws-amplify/auth/lib/Auth.js:514:16) at AuthClass.signIn (node_modules/@aws-amplify/auth/lib/Auth.js:400:25) at onUserSignIn (test/07UserCreation.js:31:14) at Context. (test/07UserCreation.js:40:9) at process.topLevelDomainCallback (domain.js:126:23)

npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! service-api@0.0.0 test-coverage-html: nyc --reporter=html mocha -timeout 10000 --exit npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the service-api@0.0.0 test-coverage-html script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

amhinson commented 3 years ago

@pathiyilnaveen Can you add global.crypto = require('crypto') at the top of the file?

pathiyilnaveen commented 3 years ago

@amhinson Thanks , I added it but still issue is seen . Should I add any specific version of crypto in my package.json ?

amhinson commented 3 years ago

No, you shouldn't have to add crypto, as it is included with Node by default now.

pathiyilnaveen commented 3 years ago

node -v : v10.19.0 I have added crypto like you suggested as well as amplify version but the same resut .

Is it working for you ? If so could you please let me know your node version and share package.json dependencies

amhinson commented 3 years ago

If you could provide a sample repo that shows the behavior you're seeing, that would be the quickest way for us to solve the issue you're seeing.

pathiyilnaveen commented 3 years ago

@amhinson Thanks so much Great Help !! I figured out where to add global.crypto = require('crypto') . We have to added this to top of the very first test file in the test folder .

amhinson commented 3 years ago

Ah ok great! Glad you were able to figure it out 🙂

bhavesh-pandey commented 3 years ago

Same issue was coming to me, it was not getting reproduced on my local dev machine, was coming only on my deployed containers. I also upgraded my amazon-cognito-identity-js to 4.5.3. but no luck but finally added global.crypto = require('crypto') in my code resolved the issue. Thanks.

Benzer1406 commented 3 years ago

@amhinson Sorry for the late reply. I tried with the latest tag and it works without issue. I can even delete the global.crypto = require('crypto');from my files. Thanks for the support!

renanwilliam commented 3 years ago

I have the same error here but can't fix it. Any updates?

amhinson commented 3 years ago

@renanwilliam could you provide what you've tried from this issue?

Benzer1406 commented 3 years ago

Just to correct one thing, I actually had to leave the 'global.crypto = requiere('crypto-JS'); on top for it to work.

renanwilliam commented 3 years ago

I've tried install latest tag and insert global.crypto = require('crypto') at the top. I'm using typescript with the code bellow:

const globalAny:any = global;
globalAny.crypto = require('crypto');

It was working before, stopped after update from 4.4.0 to 4.5.3. After rolling back to 4.4.0 come back to works.

amhinson commented 3 years ago

@renanwilliam can you share more about your app and some reproduction steps? If possible, a small sample repo that we could run to replicate the issue you're seeing would be ideal.

Ladvace commented 3 years ago

Unfortunally I'm experiencing the same error, I tried setting crypto to the top, I tried settings "resolutions": { "crypto-js": "3.1.9-1" } in the package.json but all these solutions didn't work for me

Ladvace commented 3 years ago

these are my depencies in the package.json if it could be usefull : "dependencies": { "aws-amplify": "^3.3.7", "aws-sdk": "^2.786.0", "body-parser": "^1.19.0", "compression": "^1.7.4", "cors": "^2.8.5", "express": "^4.17.1", "express-fileupload": "^1.2.0", "morgan": "^1.10.0", "node-fetch": "^2.6.1", "resource-router-middleware": "^0.7.0", "ulid": "^2.3.0", "uuid": "^8.3.1" } ,

amhinson commented 3 years ago

@Ladvace Could you share more about your app and reproduction steps? Also, you shouldn't need to add any resolutions anymore.

Can you make sure you have global.crypto = require('crypto') at the very top of your file before any imports?

Ladvace commented 3 years ago

I already have global.crypto = require('crypto'). I do nothing more than this: const signInRes = await signIn(username, password); return res.send(signInRes);

amhinson commented 3 years ago

@Ladvace Would you be able to share a small example repo that shows the behavior you're seeing? I've really been trying hard to replicate the issues you are seeing, but there are just just many different factors that might be contributing to the problem.

Ladvace commented 3 years ago

I hope this will be fine: https://pastebin.com/MYxyuMHk

amhinson commented 3 years ago

@Ladvace Thank you, that will help a lot! Is this just a standard Express app?

Ladvace commented 3 years ago

yes. the api.get you see in the pastebin it's just an express router.

let api = Router();

amhinson commented 3 years ago

Thanks again for the reproduction sample @Ladvace! I have made a small adjustment in this PR that should fix the behavior you're seeing. It is available to use now with the unstable tag, and we will likely have a release to latest next week.

Can you verify that unstable works for you?

Also, with that fix, it is no longer required to add global.crypto = require('crypto') in your code, as this will handle that automatically.

Ladvace commented 3 years ago

ok, fixed!, thanks so much

cbschuld commented 3 years ago

@amhinson - I too can confirm "unstable" with no additional require works. Thanks for the fix & the unstable push.

renanwilliam commented 3 years ago

Here works too.

minkasu-kuppusamy commented 3 years ago

How to add global.crypto = require('crypto') in build file? i mean after bundling we can do it manually, how to do before bundle starts ?

rahul-network commented 3 years ago

Please use the package "amazon-cognito-identity-js": "4.3.3" instead of "amazon-cognito-identity-js": "^4.3.3"

This ^ sysmbol will always find latest version of the package and it will break if any unstable version released or any errors.