Why am I receiving "Error: Requiring unknown module "undefined"." when using bcryptjs in react-native app

300 views Asked by At

I have imported bcryptjs for password hashing in the client (rather than server) in my react-native app. All of my code appears to be correct, but I keep getting the following error..."Error: Requiring unknown module "undefined". If you are sure the module exists, try restarting Metro. You may also want to run yarn or npm install., js engine: hermes." This error is related to my import/use of bcryptjs as it only appears when I import and/or try to use bcryptjs. Fyi, I am using expo and my emulator is android studio (don't know if that helps)

my package.json dependencies (of note: 'bcryptjs' and 'react-native-get-random-values' are both there which is in direct conflict with the error statement)...

"dependencies": {
    "@react-native-community/datetimepicker": "6.7.3",
    "@react-navigation/bottom-tabs": "^6.5.8",
    "@react-navigation/native": "^6.1.7",
    "@react-navigation/stack": "^6.3.17",
    "@reduxjs/toolkit": "^1.9.5",
    "@types/bcryptjs": "^2.4.4",
    "@types/react": "~18.0.27",
    "axios": "^1.4.0",
    "bcryptjs": "^2.4.3",
    "expo": "~48.0.18",
    "expo-linear-gradient": "~12.1.2",
    "expo-status-bar": "~1.4.4",
    "react": "18.2.0",
    "react-native": "0.71.8",
    "react-native-get-random-values": "^1.9.0",
    "react-native-ionicons": "^4.6.5",
    "react-native-linear-gradient": "^2.8.2",
    "react-native-modal-datetime-picker": "^17.1.0",
    "react-native-paper": "^5.9.1",
    "react-native-phone-input": "^1.3.7",
    "react-native-picker": "^4.3.7",
    "react-native-vector-icons": "^10.0.0",
    "react-redux": "^8.1.1",
    "typescript": "^4.9.4"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@types/react-native-get-random-values": "^1.8.0",
    "@types/react-native-vector-icons": "^6.4.13"
  },

my import statements..

import bcrypt from 'bcryptjs';
import RNPRNG from 'react-native-get-random-values';

my password hashing block (note: I am wanting to call hashPassword() every time 'confirmedPasswordValid' changes. Also, there is another state var not shown for [password, setPassword]) ...

const [hashedPassword, setHashedPassword] = useState()
  
  bcrypt.setRandomFallback((randomBytes) => {
        // Fallback to react-native-get-random-values
        const randomValuesArray = new Uint8Array(randomBytes.length);
        RNPRNG.getRandomValues(randomValuesArray); 
        randomBytes.set(randomValuesArray);
      }
    )
  
  const hashPassword = () => {
    const saltRounds = 10;
    const passwordToHash = password;

    bcrypt.genSalt(saltRounds, (err, salt) => {
      if (err) {
        //handle error modal?
        console.log(err);
      } else {
        bcrypt.hash(passwordToHash, salt, (err, hashedPassWord) => {
          if (err) {
            //handle error modal?
            console.error(err);
          } else {
            setHashedPassword(hashedPassWord);
          }
        })
      }
    })
  }

  useEffect(() => {
    hashPassword()
  }, [confirmedPasswordValid])


but again, none of this code even runs because the bcryptjs module doesn't seem to be recognized by my app, so with regard to the problem, I think this block of code is irrelevant.

I have double checked to make sure that the library does in fact exist in my pakage.json file and that I did in fact install it correctly. I have uninstalled and reinstalled the module. I have run npm install. I have rewritten my code in every way I can think of to get it to work but the error persists (which makes sense if it isn't recognizing the module then no matter what I do with my code won't help). Also, there is a package called react-native-bcrypt, but please note that the documentation for the library in npm simply directs you to the bcryptjs page and documentation - implying that there is no such thing as react-native-bcrypt and that it can therefore, not be imported. Instead just use bcryptjs. This, of course, simply brings me back to the original problem

1

There are 1 answers

0
JCWCo On

I was struggling with this a whole lot too. It may not be ideal, but this answer worked for me: https://stackoverflow.com/a/76619656/21640094

Basically, in node_modules/bcryptjs/dist/bcrypt.js, replace the random function with:

function random(len) {
    try {
        if (randomFallback)
            return randomFallback(len); 
        else if (!randomFallback)
            throw Error("Neither WebCryptoAPI nor a crypto module is available. Use bcrypt.setRandomFallback to set an alternative");
    } catch (error) {
        console.log(error);
    }
}

As far as I can tell, the problem is bcrypt trying to use crypto in the line (line 25 for me):

return require("crypto")['randomBytes'](len);

EDIT: You may need to do the same to node_modules/bcryptjs/src/bcrypt.js