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

CloudFlare Pages deployment fails with RollupError #378

Closed
yu-kani opened this issue May 11, 2023 · 24 comments
Closed

CloudFlare Pages deployment fails with RollupError #378

yu-kani opened this issue May 11, 2023 · 24 comments

Comments

@yu-kani
Copy link

yu-kani commented May 11, 2023

Environment

  • Node Version v16.15.1 / v18.15.0
  • nuxt 3.4.3
  • Nitro 2.4.0
  • @sidebase/nuxt-auth 0.5.0 / 0.6.0-beta.0
  • next-auth 4.22.1

Reproduction

No response

Describe the bug

During the deployment process on CloudFlare Pages,an error is occurring because the jose package is unable to use the createHash function from the unenv package it depends on. Specifically, the digest.js file in the jose package is importing the createHash function from the crypto package, but it needs to retrieve createHash from the crypto module of the unenv package, which is not properly exported.

Additional context

I have tried the following and would like to report an issue:

  • Removing the nuxt-auth module from nuxt.config.ts allows the application to function correctly.
  • The issue occurs regardless of the version of nuxt-auth used.
  • The issue persists even when NODE_VERSION is changed between v14 and v19.
  • When using nitro.preset='node-server', the build succeeds but the output shows an error.
  • When specifying nitro.rollupConfig.plugins: [ignore(["jose"])], the error changes from 'createHash' to 'createHmac'.

Logs

08:45:06.136	[info] [nitro] Building Nitro Server (preset: `cloudflare-pages`)
08:45:48.545	[error] [nitro] RollupError: "createHash" is not exported by "node_modules/unenv/runtime/node/crypto/index.mjs", imported by "node_modules/openid-client/node_modules/jose/dist/node/esm/runtime/digest.js".
08:45:48.546	
08:45:48.546	
08:45:48.546	1: import { createHash } from 'crypto';
08:45:48.546	            ^
08:45:48.546	2: const digest = (algorithm, data) => createHash(algorithm).update(data).digest();
08:45:48.546	3: export default digest;
08:45:48.548	[error] "createHash" is not exported by "node_modules/unenv/runtime/node/crypto/index.mjs", imported by "node_modules/openid-client/node_modules/jose/dist/node/esm/runtime/digest.js".
08:45:48.549	  at error (node_modules/nuxt/node_modules/rollup/dist/es/shared/node-entry.js:2128:30)
08:45:48.549	  at Module.error (node_modules/nuxt/node_modules/rollup/dist/es/shared/node-entry.js:13322:16)
08:45:48.549	  at Module.traceVariable (node_modules/nuxt/node_modules/rollup/dist/es/shared/node-entry.js:13707:29)
08:45:48.549	  at ModuleScope.findVariable (node_modules/nuxt/node_modules/rollup/dist/es/shared/node-entry.js:12210:39)
08:45:48.549	  at ReturnValueScope.findVariable (node_modules/nuxt/node_modules/rollup/dist/es/shared/node-entry.js:6953:38)
08:45:48.549	  at Identifier.bind (node_modules/nuxt/node_modules/rollup/dist/es/shared/node-entry.js:8103:40)
08:45:48.550	  at CallExpression.bind (node_modules/nuxt/node_modules/rollup/dist/es/shared/node-entry.js:5749:23)
08:45:48.550	  at CallExpression.bind (node_modules/nuxt/node_modules/rollup/dist/es/shared/node-entry.js:9630:15)
08:45:48.550	  at MemberExpression.bind (node_modules/nuxt/node_modules/rollup/dist/es/shared/node-entry.js:5749:23)
08:45:48.550	  at MemberExpression.bind (node_modules/nuxt/node_modules/rollup/dist/es/shared/node-entry.js:9291:19)
08:45:48.701	error Command failed with exit code 1.
08:45:48.702	info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
08:45:48.727	Failed: build command exited with code: 1
08:45:49.934	Failed: error occurred while running build command
@yu-kani yu-kani added the bug label May 11, 2023
@Jaimeer
Copy link

Jaimeer commented May 12, 2023

+1

@BracketJohn
Copy link
Contributor

Hey @yu-kani 👋

Thanks for reporting:

  • could you please provide a reproduction?
  • how do you deduce that this is related to nuxt-auth? nuxt-auth does not directly depend on jose or crypto

I think this rather related to authjs / next-auth as they depend on jose, see https://github.com/nextauthjs/next-auth/blob/main/packages/core/package.json -> so you'd have to file the problem in their repo / look into their repo to see if they already have a similar issue.

@yu-kani
Copy link
Author

yu-kani commented May 14, 2023

Hey @BracketJohn

Thank you for your assistance.
I have prepared a repository where the error can be reproduced.
The reproduction steps are as follows:

Repository where the error is reproduced

https://github.com/yu-kani/nuxt-auth-test

Pattern 1

  1. Clone the repository to your local machine.
  2. Run yarn build.

Pattern 2

  1. Publish the Git repository to Cloudflare Pages.
  2. Set the environment variable NODE_VERSION = v18.16.0 in Cloudflare Pages.
  3. Deploy the repository.
  4. The error can be confirmed.

I am considering whether the cause lies in nuxt-auth or jose, but I do not have detailed knowledge and therefore do not know for sure. I am sorry.

@cliqer
Copy link

cliqer commented Jun 5, 2023

@BracketJohn I solved a similar error with cloudflare workers crypto compatibility.
Maybe it gives you some ideas on how to fix:

import {isDevelopment} from "std-env";

if (isDevelopment && typeof window === 'undefined') {
    import('crypto').then(crypto => globalThis.crypto = crypto);
}

export default defineEventHandler(async event => {
    const {uid} = getQuery(event);

    const sharedSecret = 'a-secure-password';
    const turnServer = 'turn.example.com';
    const ttl = 86400;
    const username = Math.floor(Date.now() / 1000) + ttl
    const encoder = new TextEncoder();
    const data = encoder.encode(username.toString());
    const keyData = encoder.encode(sharedSecret);

    const key = await crypto?.subtle?.importKey(
        'raw',
        keyData,
        { name: 'HMAC', hash: 'SHA-1' },
        false,
        ['sign']
    );

    const signature = await crypto?.subtle.sign('HMAC', key, data);
    const password = Buffer.from(signature).toString('base64');
    // const password = base64url.encode(Buffer.from(new Uint8Array(signature)));

    return {
        username,
        password,
        ttl
    };
})

@jharris-tc
Copy link

I had this same issue in my nuxt deployment.

I am not a javascript expert, but from looking at the dependencies it seems that jose is used by next-auth, which is a peer dependency with nuxt-auth. unenv, which seems to be a polyfilling library, is used by nitropack, which is used by nuxt-auth. unenv has now polyfilled the crypto library, but without the createHash and createHMAC functions.

My solution was just to pin unenv to 1.2.2, which is the version before it added crypto support.

I am not sure if there is a way to make a PR to unenv to like pass on the functions it doesnt polyfil, but I do not know enough about node or JS to do that.

TL;DR -> hard pin/override unenv to be version 1.2.2

@yu-kani
Copy link
Author

yu-kani commented Jun 27, 2023

@jharris-tc thanks for the investigation.

I'm still not getting a successful build myself.

Environment

  • Node Version v18.16.0
  • nuxt 3.6.1
  • Nitro 2.4.0
  • @sidebase/nuxt-auth 0.6.0-beta.3
  • next-auth 4.22.1

package

yarn add [email protected]

Result

yarn build

15:05:25.377 [info] [nitro] Building Nitro Server (preset: cloudflare-pages)
15:05:26.829 [error] [nitro] Error: Could not load /opt/buildhome/repo/node_modules/unenv/runtime/node/crypto/index.mjs (imported by node_modules/uncrypto/dist/crypto.node.mjs): ENOENT: no such file or directory, open '/opt/buildhome/repo/node_modules/unenv/runtime/node/crypto/index.mjs'
15:05:26.829  
15:05:26.830  
15:05:26.830 undefined
15:05:26.830 [error] Could not load /opt/buildhome/repo/node_modules/unenv/runtime/node/crypto/index.mjs (imported by node_modules/uncrypto/dist/crypto.node.mjs): ENOENT: no such file or directory, open '/opt/buildhome/repo/node_modules/unenv/runtime/node/crypto/index.mjs'
15:05:26.830  
15:05:26.873 error Command failed with exit code 1.
15:05:26.873 info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
15:05:26.900 Failed: build command exited with code: 1
15:05:27.832 Failed: error occurred while running build command

@gritworks
Copy link

I had this same issue in my nuxt deployment.

I am not a javascript expert, but from looking at the dependencies it seems that jose is used by next-auth, which is a peer dependency with nuxt-auth. unenv, which seems to be a polyfilling library, is used by nitropack, which is used by nuxt-auth. unenv has now polyfilled the crypto library, but without the createHash and createHMAC functions.

My solution was just to pin unenv to 1.2.2, which is the version before it added crypto support.

I am not sure if there is a way to make a PR to unenv to like pass on the functions it doesnt polyfil, but I do not know enough about node or JS to do that.

TL

and indeed looking at unenv the sourcecode says:
(https://github.com/unjs/unenv/blob/main/src/runtime/node/crypto/index.ts)

// TODO: Add missing exports (typecheck is not working!)
export default {
randomUUID,
getRandomValues,
randomBytes,
subtle,
webcrypto,
};

This is not an issue with nuxt-auth itself.
hope this gets fixed soon.

@jharris-tc
Copy link

here is my package.json

{
  "private": true,
  "scripts": {
    "build": "nuxt build",
    "dev": "nuxt dev",
    "generate": "nuxt generate",
    "preview": "nuxt preview",
    "postinstall": "nuxt prepare"
  },
  "devDependencies": {
    "@nuxt/devtools": "^0.4.6",
    "@pinia-plugin-persistedstate/nuxt": "^1.1.1",
    "@sidebase/nuxt-auth": "^0.4.0",
    "@stripe/stripe-js": "^1.54.1",
    "nuxt": "^3.1.2",
    "vue-stripe-js": "^1.0.1"
  },
  "dependencies": {
    "@aws-amplify/ui-vue": "^3.1.7",
    "@nuxtjs/axios": "^5.13.6",
    "@pinia/nuxt": "^0.4.8",
    "@tucowsinc/vue-ui-styling-dxp": "^0.0.2",
    "@vee-validate/nuxt": "^4.9.5",
    "aws-amplify": "^5.0.14",
    "less": "^4.1.3",
    "pinia": "^2.0.34"
  },
  "overrides": {
    "@sidebase/nuxt-auth": {
      "unenv": "1.2.2"
    }
  }
}

hopefully this helps, I just ran it again with npm clean-install --progress=false -> npm run build -> the publish action via GHA (this also worked using the cloudflare pages dashboard, but we moved it out of there to have better visibility of logs) and it was fine

seems like your versions might be ahead of mine, hope you can figure it out

@gritworks
Copy link

gritworks commented Jun 27, 2023

ah, thanks. i searched my eyes out trying to understand the overrides.
I think this is also needed (for my setup and maybe for others) to override it for
nitropack (also using crypto)

-- edit --

from bad to worse i guess.
this spawns a heap of new errors. and eventually the build fails with:

Error: Failed to publish your Function. Got error: Uncaught TypeError: Object prototype may only be an Object or null: undefined
at functionsWorker-0.8747573045606203.js:5837:41 in Ir.exports
at functionsWorker-0.8747573045606203.js:7375:4

i guess jose depends on more features implemented in newer version of unenv:

node_modules/jose/dist/node/esm/runtime/is_key_object.js (3:20) "types" is not exported by "node_modules/unenv/runtime/node/util/index.mjs", imported by "node_modules/jose/dist/node/esm/runtime/is_key_object.js".

the quickest fix for this would be unenv completing the missing crypto functions like createHash.

thanks for the effort though, its appreciated.

@AwesomeDude091
Copy link

Can confirm this is an issue

@jharris-tc
Copy link

ah, thanks. i searched my eyes out trying to understand the overrides. I think this is also needed (for my setup and maybe for others) to override it for nitropack (also using crypto)

-- edit --

from bad to worse i guess. this spawns a heap of new errors. and eventually the build fails with:

Error: Failed to publish your Function. Got error: Uncaught TypeError: Object prototype may only be an Object or null: undefined at functionsWorker-0.8747573045606203.js:5837:41 in Ir.exports at functionsWorker-0.8747573045606203.js:7375:4

i guess jose depends on more features implemented in newer version of unenv:

node_modules/jose/dist/node/esm/runtime/is_key_object.js (3:20) "types" is not exported by "node_modules/unenv/runtime/node/util/index.mjs", imported by "node_modules/jose/dist/node/esm/runtime/is_key_object.js".

the quickest fix for this would be unenv completing the missing crypto functions like createHash.

thanks for the effort though, its appreciated.

I get the types is not exported, unenv -> esm too, but it seems okay? I agree the cleanest fix is to unenv

@AwesomeDude091
Copy link

Until Unenv fixes it there end is there a temporary fix that could be implemented?

@Hebilicious
Copy link

Hebilicious commented Jun 30, 2023

This happens because next-auth is not really compatible with cloudflare workers out of the box.
For anyone that has this issue and need a working solution, I created a different module that integrates directly with auth.js, in a more straightforward way. It's significantly simpler in scope compared to sidebase, and I'm using it for Cloudflare Pages / Cloudflare Workers without any issues.

I've also documented some of the workaround that you need to fix some of the nitro/unenv build issues that you'll have due to authjs/pnpm/unenv

https://github.com/Hebilicious/authjs-nuxt

Maybe the sidebase team is interested into using this approach for a v1 ?

@Otoris
Copy link

Otoris commented Jul 21, 2023

Still getting this as well. Considering switching to @Hebilicious repo but that's a ton of work 😢 .

@Hebilicious
Copy link

Still getting this as well. Considering switching to @Hebilicious repo but that's a ton of work 😢 .

What features do you need that are missing ?

@Otoris
Copy link

Otoris commented Jul 22, 2023

Still getting this as well. Considering switching to @Hebilicious repo but that's a ton of work 😢 .

What features do you need that are missing ?

I don't think anything is missing - just complaining it is a lot of work to switch libraries. I just put together a proof of concept to investigate however! I left an issue on your repo that is a potential blocker for me, but maybe you've run into this before. Hebilicious/authjs-nuxt#43

@Hebilicious
Copy link

@Otoris Thanks, just pushed a fix for this issue.

@theleaks
Copy link

ah, thanks. i searched my eyes out trying to understand the overrides. I think this is also needed (for my setup and maybe for others) to override it for nitropack (also using crypto)

-- edit --

from bad to worse i guess. this spawns a heap of new errors. and eventually the build fails with:

Error: Failed to publish your Function. Got error: Uncaught TypeError: Object prototype may only be an Object or null: undefined at functionsWorker-0.8747573045606203.js:5837:41 in Ir.exports at functionsWorker-0.8747573045606203.js:7375:4

i guess jose depends on more features implemented in newer version of unenv:

node_modules/jose/dist/node/esm/runtime/is_key_object.js (3:20) "types" is not exported by "node_modules/unenv/runtime/node/util/index.mjs", imported by "node_modules/jose/dist/node/esm/runtime/is_key_object.js".

the quickest fix for this would be unenv completing the missing crypto functions like createHash.

thanks for the effort though, its appreciated.

I'm having this problem when trying to build cloudflare for Nuxt.

When I import the ethers package, I have a problem because of the crypto package.

@ethersproject/providers I tried to use it, this time I got the same error as yours. How can we solve the problem?
I want to use ethers but I can't deploy to cloudflare.

@AwesomeDude091
Copy link

You have to either migrate away from dependencies that require inbuilt node libraries (i.e. node:crypto) or you check which inbuilt node libraries are the root of the failed build (for Sidebase it is Node Crypto) and then hope that a polyfill is developed for that library. The gist of the error is that a dependency requires an inbuilt Node JS library, which is not present in a edge runtime environment such as Cloudflare Pages. Somebody then has to stich together a bridge between the NodeJS library and the edge environments (polyfill).

Here is an incomplete polyfill of the Node Crypto library being worked on in the unenv project.
unjs/unenv#111

@zoey-kaiser
Copy link
Member

In version 0.6, we introduced the local providor, this should (did not test it myself) work with cloudflare workers. Otherwise, it is now also possible for the community to use NuxtAuth as a framework to write their own providors, which would allow someone in the community to also write their own support. (See #495 as an example)

I will go ahead and close this issue for now, as I don't see our team being able to futhur tackle this deployment issue. If an issue arrises with deploying the local providor to cloudflare, feel free to open a new issue and we can discuss it there!

@AwesomeDude091
Copy link

Would this mean that there is compatibility for using OAuth2 Providers?

@zoey-kaiser
Copy link
Member

Would this mean that there is compatibility for using OAuth2 Providers?

As mentioned by @Hebilicious, NextAuth, the OAuth package we use under the hood, does not support cloudflare workers, which means that with out current implementation, there will be no support for them, until NextAuth adds support. Sadly this means we are bound by their implementation and cannot overwrite or change this, unless we completly move away from their systems.

@AwesomeDude091
Copy link

Is there any plans to do that?

@zoey-kaiser
Copy link
Member

Is there any plans to do that?

With version 0.6, we do open the doors, to allow this, however re-implementing every oAuth provider, that NextAuth has, will take its time. We hope to be able to make NuxtAuth more extendable for others, that you could easily add the configuration for the oAuth provider you wish to use.

But first, my goal is to iron out the last issues with 0.6 and get it released. Once we did this, I can discuss with the team what we could add to the roadmap. However, I do understand, this would be nice to add and have added it to my list!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests