Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Version >=7.0.0 is not compatible with React Native / Expo #375

Closed
dylancom opened this issue Feb 24, 2020 · 72 comments · Fixed by #385, #515, statisticsnorway/ssb-component-library#256, Imageus-OSS/server#33 or concourse/concourse#6684
Labels
waiting-for-upstream Waiting for upstream fixes

Comments

@dylancom
Copy link

When I'm upgrading from 3.4.0 to 7.0.0 an error saying it can't require "crypto" pops up in a React Native app. It used to work fine before.

@VandalPaulius
Copy link

+1
v7 isn't compatible with AWS Lambda as well. I get uuid: This browser does not seem to support crypto.getRandomValues(). error, which sounds exactly like @dylancompanjen error

@jvpelt
Copy link

jvpelt commented Feb 24, 2020

Same goes for Azure functions. Getting the message:

uuid: This browser does not seem to support crypto.getRandomValues(). If you need to support this browser, please provide a custom random number generator through options.

@ibc
Copy link

ibc commented Feb 24, 2020

Is this just affecting React Native? or also desktop browsers? I have like MANY libs for Node and browser that depends on uuid...

@ctavan
Copy link
Member

ctavan commented Feb 24, 2020

Thanks for the reports, we‘ll have to investigate.

Could anyone of you provide a minimal reproduction case? That would be extremely helpful!

@ibc
Copy link

ibc commented Feb 24, 2020

I just confirm that the issue does NOT happen in browsers (using uuid 7.0.0 with browserify). So it may be something just related to react-native, but I cannot check that.

@broofa broofa added the more info needed Issue not actionable w/out additional details label Feb 24, 2020
@TrySound
Copy link
Member

Check this
https://github.com/ai/nanoid#react-native

@ctavan
Copy link
Member

ctavan commented Feb 24, 2020

@TrySound thanks for the hint, maybe we can go a similar route. Will check it out in detail.

@ZebraFlesh
Copy link

ZebraFlesh commented Feb 24, 2020

Could anyone of you provide a minimal reproduction case? That would be extremely helpful!

I think the issue is that node LTS (12.16.1 as of this message) does not offer the crypto.getRandomValues API. Hence anything that uses node (react-native, AWS Lambda, Azure Functions, etc.) will fail. Here's the minimally reproducible test case in a node REPL:

;{
const crypto = require('crypto');
console.log('TLS 1.3: ', crypto.constants.TLS1_3_VERSION); // prove the import works
crypto.getRandomValues();
}

Output:

TLS 1.3: 772
Uncaught TypeError: crypto.getRandomValues is not a function

@TrySound
Copy link
Member

@ZebraFlesh You are right getRandomValues is not part of node crypto. Also it's not used in node version.
https://github.com/uuidjs/uuid/blob/master/src/rng.js#L4
getRandomValues is used in browser version and it's correct.
https://github.com/uuidjs/uuid/blob/master/src/rng-browser.js

The problem are environments. They provides own sandboxes.

@ZebraFlesh
Copy link

Here's what I know: performing the following code in a serverless handler which is bundled with webpack fails with the crypto.getRandomValues is not a function message:

import { v1 as uuidv1 } from 'uuid';
export const serve = async (event) => {
  const value = uuidv1();
};

Looking at @TrySound's links it's very strange to me that this would go into the browser code instead of the node variant, but it is. (And my webpack config explicitly has a target: 'node' line.)

@TrySound
Copy link
Member

Very good catch!

@ctavan main does not always mean node environment and module does not always mean browser environment. There is special browser field for this. You should provide commonjs and esm for both node and browser environment.

Look how this is solved here in react-map-gl project
https://github.com/uber/react-map-gl/blob/master/package.json#L17-L25

@ZebraFlesh
Copy link

ZebraFlesh commented Feb 24, 2020

main does not always mean node environment and module does not always mean browser environment. There is special browser field for this.

Jeez. It took a bit of digging to unpack all that, but you totally nailed it and made me smarter -- so thank you! Here's a link to npm's docs on browser; I couldn't find a concise explainer on module though (looks like it's mostly a proposal that most things are respecting, but not yet formalized in a spec).

@TrySound
Copy link
Member

Here's spec
https://github.com/defunctzombie/package-browser-field-spec

Also you can do the same to provide react-native specific solution
https://github.com/ai/nanoid/blob/master/package.json#L30-L32

@TrySound
Copy link
Member

"module" field is just a convention. Modern bundlers prefer it over "main". Though node will provide soon conditional exports as official solution.
https://nodejs.org/api/esm.html#esm_conditional_exports

@ctavan
Copy link
Member

ctavan commented Feb 24, 2020

I believe we have two distinct issues in this one:

  1. This module currently doesn't seem to be compatible with react-native since react-native seems to use the browser code of this library but doesn't expose the WebCrypto global crytpo object. We'll likely be able to provide a fix for this case similar as nanoid does by providing an override in the package.json's react-native field: https://github.com/ai/nanoid/blob/master/package.json#L30-L32

  2. This module apparently doesn't work in Azure functions for similar reasons: Apparently Azure functions try to invoke browser code while it should run the node code. I have created a separate issue to track the Azure functions problem: Version 7.0.0 not compatible with Azure Functions/AWS Lambda/Google Cloud Functions #378

With regards to react-native I'm happy to take a deeper look at the solution that nanoid chose but I'm equally happy to accept pull-requests that add such a feature.

The good news is that all of the implementations that are now broken very likely were using flawed random number generators with a much higher likelihood of UUID collisions (see https://github.com/tc39/proposal-uuid#how-unique-are-v4-uuids for examples) so we're finally discovering those implementations and now have a chance to fix them.

@evdama
Copy link

evdama commented Feb 25, 2020

Same goes for Azure functions. Getting the message:

uuid: This browser does not seem to support crypto.getRandomValues(). If you need to support this browser, please provide a custom random number generator through options.

Same as for AWS, Azure, is also true for google cloud functions such as firebase cloud functions:

error from setNonceMiddleware: Error: uuid: This browser does not seem to support crypto.getRandomValues(). If you need to support this browser, please provide a custom random number generator through options.rng.

@TrySound
Copy link
Member

@ctavan 3. Also main/module is confused with node/browser

@ctavan
Copy link
Member

ctavan commented Feb 25, 2020

Looking at nanoid it looks like a solution for react-native is unfortunately not 100% straightforward: The random number generators used in node (crypto.randomBytes()) and the browser (crypto.getRandomValues()) are both synchronous. Hence all methods that this library exposes so far are synchronous as well.

The approach that nanoid takes is to offer async variants of the methods and then makes use of expo-random to generate cryptographically secure random numbers.

Nanoid also offers non-secure variants which use Math.random() under the hood. We have explicitly removed insecure random number generation in #354 with the latest major version upgrade and we will not add them for react-native.

That said there seem to be plenty of attempts on npm to provide Polyfills for either node's crypto.randomBytes() or WebCrypto crypto.getRandomValues() for react-native: https://www.npmjs.com/search?q=react%20native%20random

However I found it really hard to judge if any of these implementations satisfy the two criteria

  1. synchronous
  2. cryptographically secure pseudo random numbers

@LinusU I saw that you authored one of these libraries (https://github.com/LinusU/react-native-get-random-values) and since you have been contributing to this library as well, maybe you can shed a bit more light on the situation w.r.t. sync CSPRNGs in react-native (or anyone else who is familiar with the matter)?

@slavikdenis
Copy link

I think it's fixed in version 7.0.1

@EugeneDraitsev
Copy link

I still have the same error in 7.0.1

import { v4 as uuid4 } from 'uuid'
uuid4()
Error: uuid: This browser does not seem to support crypto.getRandomValues().
If you need to support this browser, please provide a custom random number generator through options.rng.

@lorenc-tomasz

This comment has been minimized.

@ctavan
Copy link
Member

ctavan commented Feb 26, 2020

The react-native problem has not yet been fixed and as explained above a fix is not straightforward.

7.0.1 fixed problem with Node.js cloud environments.

@LinusU
Copy link
Member

LinusU commented Feb 26, 2020

@ctavan I think it's very unfortunate that React Native doesn't provide a proper crypto.getRandomValues out of the box 😞

Personally, I think that the best approach is to have instructions to install the react-native-get-random-values polyfill and load that in at the setup for React Native users. That way they get a proper RNG, and the usage would be transparent since you only have to add the global polypill once.

Something like:

React Native: If you are using this library together in React Native, you need to add a polyfill for crypto.getRandomValues. We recommend using react-native-get-random-values.

I'd be happy to update documentation in that package as well if there is anything that is unclear 👍


oh, and for anyone else in this thread, if you want a fix to this problem you should be able to install react-native-get-random-values and add import 'react-native-get-random-values' to the top of your index.js. Than the uuid package should work magically!

@ctavan
Copy link
Member

ctavan commented Feb 26, 2020

Thank you so much for your contributions!

I think we could go even one step further and make this work out of the box using a react-native field in package.json. However documenting how to install a Polyfill might also be a viable solution, in particular since we would define the polyfill as a peerDependency only anyways, so there would be an extra npm install involved anyways…

Just one thing I'm really curious about: Does your polyfill use a random number generator on both platforms (iOS and Android) that qualifies as "cryptographically secure"? And if so, why on earth do all other polyfill libraries for react-native that I found out there only provide async methods and no sync methods (most that I found seem to be using https://www.npmjs.com/package/sjcl as a fallback for their sync implementations)?

So I'm happy to merge your changes I just want to ensure that we are getting the same quality of randomness that we get with node and webcrypto.

@LinusU
Copy link
Member

LinusU commented Feb 27, 2020

@ctavan

I think we could go even one step further and make this work out of the box using a react-native field in package.json.

I'm not exactly sure what we would put in that file? Do you mean that it would require the polyfill there? 🤔

However documenting how to install a Polyfill might also be a viable solution, in particular since we would define the polyfill as a peerDependency only anyways, so there would be an extra npm install involved anyways…

I'm not sure that declaring react-native-get-random-values as a peerDependency is the best way forward, since that will give an "unmet peer dependency" warning for anyone using uuid on Node.js/browsers.

Just one thing I'm really curious about: Does your polyfill use a random number generator on both platforms (iOS and Android) that qualifies as "cryptographically secure"?

It does. It uses SecRandomCopyBytes on iOS and SecureRandom on Android.

And if so, why on earth do all other polyfill libraries for react-native that I found out there only provide async methods and no sync methods (most that I found seem to be using https://www.npmjs.com/package/sjcl as a fallback for their sync implementations)?

The fact that you can have synchronous methods in a React Native module isn't all that well documented. In fact, I only found out when I tried to add crypto.getRandomValues directly to React Native.

So I'm happy to merge your changes I just want to ensure that we are getting the same quality of randomness that we get with node and webcrypto.

Sounds good 👍

ctavan added a commit that referenced this issue Oct 4, 2020
Thanks to
LinusU/react-native-get-random-values#13 Expo
finally has support for a sync CSPRNG.

Fixes #375
@ctavan
Copy link
Member

ctavan commented Oct 4, 2020

With expo@39 and react-native-get-random-values@1.5 this is finally working as intended.

See:

@jameswoodley
Copy link

This issue also refers to the problems with Azure Functions/AWS Lambda/Firebase Functions etc too. Are we saying the same resolution is to use the react-native-get-random-values package?

@mikehardy
Copy link

@jameswoodley I don't think so. For node.js environments this is working now without extra packages. For react-native you must also install a random number generator, react-native-get-random-values works

These are my current dependencies, all tested + working + in production; firebase is cloud functions, public-app is react-native

mike@isabela:~/work/Kullki/ksocialscore/packages (navigation-overhaul) % cat firebase/package.json |egrep 'uuid|random'
    "@types/uuid": "^8.3.0",
    "uuid": "^8.3.2"
mike@isabela:~/work/Kullki/ksocialscore/packages (navigation-overhaul) % cat public-app/package.json |egrep 'uuid|random'
    "@types/uuid": "^8.3.0",
    "react-native-get-random-values": "^1.6.0",
    "uuid": "^8.3.2",

@jameswoodley
Copy link

Hi @mikehardy thanks for the update. I found that rollup was defaulting to browser and not node. Have resolved by adding

exportConditions: ['node'] to the resolve plugin

Thanks!

@ctavan
Copy link
Member

ctavan commented Mar 14, 2021

@jameswoodley the issue you are describing is being tracked in #544

srchase pushed a commit to srchase/smithy-typescript that referenced this issue Mar 17, 2023
Current uuid is not compatible with RN/Expo at all.
See uuidjs/uuid#375
srchase pushed a commit to srchase/smithy-typescript that referenced this issue Mar 21, 2023
Current uuid is not compatible with RN/Expo at all.
See uuidjs/uuid#375
srchase pushed a commit to smithy-lang/smithy-typescript that referenced this issue Mar 23, 2023
Current uuid is not compatible with RN/Expo at all.
See uuidjs/uuid#375
srchase pushed a commit to smithy-lang/smithy-typescript that referenced this issue Apr 17, 2023
Current uuid is not compatible with RN/Expo at all.
See uuidjs/uuid#375
srchase pushed a commit to srchase/smithy-typescript that referenced this issue Apr 19, 2023
Current uuid is not compatible with RN/Expo at all.
See uuidjs/uuid#375
srchase pushed a commit to srchase/smithy-typescript that referenced this issue Jun 1, 2023
Current uuid is not compatible with RN/Expo at all.
See uuidjs/uuid#375
srchase pushed a commit to smithy-lang/smithy-typescript that referenced this issue Jun 16, 2023
Current uuid is not compatible with RN/Expo at all.
See uuidjs/uuid#375
Vylpes pushed a commit to Vylpes/Droplet that referenced this issue Sep 14, 2023
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [uuid](https://github.com/uuidjs/uuid) | dependencies | major | [`^8.3.2` -> `^9.0.0`](https://renovatebot.com/diffs/npm/uuid/8.3.2/9.0.0) |
| [@types/uuid](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/uuid) ([source](https://github.com/DefinitelyTyped/DefinitelyTyped)) | dependencies | major | [`^8.3.0` -> `^9.0.0`](https://renovatebot.com/diffs/npm/@types%2fuuid/8.3.0/9.0.1) |

---

### Release Notes

<details>
<summary>uuidjs/uuid</summary>

### [`v9.0.0`](https://github.com/uuidjs/uuid/blob/HEAD/CHANGELOG.md#&#8203;900-httpsgithubcomuuidjsuuidcomparev832v900-2022-09-05)

[Compare Source](uuidjs/uuid@v8.3.2...v9.0.0)

##### ⚠ BREAKING CHANGES

-   Drop Node.js 10.x support. This library always aims at supporting one EOLed LTS release which by this time now is 12.x which has reached EOL 30 Apr 2022.

-   Remove the minified UMD build from the package.

    Minified code is hard to audit and since this is a widely used library it seems more appropriate nowadays to optimize for auditability than to ship a legacy module format that, at best, serves educational purposes nowadays.

    For production browser use cases, users should be using a bundler. For educational purposes, today's online sandboxes like replit.com offer convenient ways to load npm modules, so the use case for UMD through repos like UNPKG or jsDelivr has largely vanished.

-   Drop IE 11 and Safari 10 support. Drop support for browsers that don't correctly implement const/let and default arguments, and no longer transpile the browser build to ES2015.

    This also removes the fallback on msCrypto instead of the crypto API.

    Browser tests are run in the first supported version of each supported browser and in the latest (as of this commit) version available on Browserstack.

##### Features

-   optimize uuid.v1 by 1.3x uuid.v4 by 4.3x (430%) ([#&#8203;597](uuidjs/uuid#597)) ([3a033f6](uuidjs/uuid@3a033f6))
-   remove UMD build ([#&#8203;645](uuidjs/uuid#645)) ([e948a0f](uuidjs/uuid@e948a0f)), closes [#&#8203;620](uuidjs/uuid#620)
-   use native crypto.randomUUID when available ([#&#8203;600](uuidjs/uuid#600)) ([c9e076c](uuidjs/uuid@c9e076c))

##### Bug Fixes

-   add Jest/jsdom compatibility ([#&#8203;642](uuidjs/uuid#642)) ([16f9c46](uuidjs/uuid@16f9c46))
-   change default export to named function ([#&#8203;545](uuidjs/uuid#545)) ([c57bc5a](uuidjs/uuid@c57bc5a))
-   handle error when parameter is not set in v3 and v5 ([#&#8203;622](uuidjs/uuid#622)) ([fcd7388](uuidjs/uuid@fcd7388))
-   run npm audit fix ([#&#8203;644](uuidjs/uuid#644)) ([04686f5](uuidjs/uuid@04686f5))
-   upgrading from uuid3 broken link ([#&#8203;568](uuidjs/uuid#568)) ([1c849da](uuidjs/uuid@1c849da))

##### build

-   drop Node.js 8.x from babel transpile target ([#&#8203;603](uuidjs/uuid#603)) ([aa11485](uuidjs/uuid@aa11485))

-   drop support for legacy browsers (IE11, Safari 10) ([#&#8203;604](uuidjs/uuid#604)) ([0f433e5](uuidjs/uuid@0f433e5))

-   drop node 10.x to upgrade dev dependencies ([#&#8203;653](uuidjs/uuid#653)) ([28a5712](uuidjs/uuid@28a5712)), closes [#&#8203;643](uuidjs/uuid#643)

##### [8.3.2](uuidjs/uuid@v8.3.1...v8.3.2) (2020-12-08)

##### Bug Fixes

-   lazy load getRandomValues ([#&#8203;537](uuidjs/uuid#537)) ([16c8f6d](uuidjs/uuid@16c8f6d)), closes [#&#8203;536](uuidjs/uuid#536)

##### [8.3.1](uuidjs/uuid@v8.3.0...v8.3.1) (2020-10-04)

##### Bug Fixes

-   support expo>=39.0.0 ([#&#8203;515](uuidjs/uuid#515)) ([c65a0f3](uuidjs/uuid@c65a0f3)), closes [#&#8203;375](uuidjs/uuid#375)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these updates again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNC43NC4yIiwidXBkYXRlZEluVmVyIjoiMzQuNzQuMiJ9-->

Co-authored-by: Renovate Bot <renovate@vylpes.com>
Reviewed-on: https://gitea.vylpes.xyz/RabbitLabs/Droplet/pulls/111
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: RenovateBot <renovate@vylpes.com>
Co-committed-by: RenovateBot <renovate@vylpes.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment