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

Preact will cause the mongodb package to not be found? #2622

Closed
Patryks1 opened this issue Aug 28, 2021 · 27 comments
Closed

Preact will cause the mongodb package to not be found? #2622

Patryks1 opened this issue Aug 28, 2021 · 27 comments
Labels
adapters Changes related to the core code concerning database adapters bug Something isn't working

Comments

@Patryks1
Copy link
Contributor

Patryks1 commented Aug 28, 2021

Question 💬

When using nextjs with Preact the database part of auth will fail with -

https://next-auth.js.org/errors#oauth_callback_handler_error Error: no optional dependency [mongodb] defined in peerOptionalDependencies in any package.json
    at find_package_json_with_name (C:\Users\node_modules\require_optional\index.js:56:11)
    at require_optional (C:\Users\node_modules\require_optional\index.js:69:13)
    at Object.getAdapter (C:\Users\node_modules\@next-auth\typeorm-legacy-adapter\dist\index.js:104:55)
    at runMicrotasks (<anonymous>)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at async Object.callback (C:\Users\.next\server\pages\api\auth\[...nextauth].js:5308:42)

I have tried to add the OptionalDependenciesand peerOptionalDependencies but both lead to the same error.

Is this a bug / Indented behaviour ? If so is there a way around it while still using preact? Removing pReact will fix this issue.

EDIT:
Looking at previous PR's seems like this is more of a bug, Here is extra details if required -

System:
    OS: Windows 10 10.0.19043
    CPU: (24) x64 AMD Ryzen 9 5900X 12-Core Processor
    Memory: 17.34 GB / 31.92 GB
  Binaries:
    Node: 14.17.2 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.10 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 7.21.1 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Spartan (44.19041.1023.0), Chromium (92.0.902.84)
    Internet Explorer: 11.0.19041.906
  npmPackages:
    @preact/compat:  17.0.2
    next: ^11.1.0 => 11.1.0
    next-auth: ^3.29.0 => 3.29.0

How to reproduce ☕️

Sandbox - https://codesandbox.io/s/elated-rumple-yu39t

Contributing 🙌🏽

Yes, I am willing to help answer this question in a PR

@Patryks1 Patryks1 added the question Ask how to do something or how something works label Aug 28, 2021
@Patryks1 Patryks1 changed the title Preact will cause the mongodb package to not be found. Preact will cause the mongodb package to not be found? Aug 28, 2021
@balazsorban44
Copy link
Member

Are you actually using mongodb, or you tried to add it to fix the problem?

We are nearing a major release that will make this problem go away by explicitly requiring users to import the adapters they are using, and in case if you don't, the problem you are reporting just won't exist.

Any chance you want to give it a try?

Check out next-auth@4.0.0-next.24

https://docs-nextauthjs.vercel.app/getting-started/upgrade-v4

API is pretty much stable now, only expected changes are bug fixes/ minor tweaks.

@Patryks1
Copy link
Contributor Author

Are you actually using mongodb, or you tried to add it to fix the problem?

We are nearing a major release that will make this problem go away by explicitly requiring users to import the adapters they are using, and in case if you don't, the problem you are reporting just won't exist.

Any chance you want to give it a try?

Check out next-auth@4.0.0-next.24

https://docs-nextauthjs.vercel.app/getting-started/upgrade-v4

API is pretty much stable now, only expected changes are bug fixes/ minor tweaks.

Yeah the actual project i am using next-auth in is using mongodb/Mongoose with next-auth. The sandbox just replicates the issue with same preact setup my main project has.

I will give V4 a go to see if it fixes the issue.

@Patryks1 Patryks1 reopened this Aug 28, 2021
@balazsorban44
Copy link
Member

Here is a pure mongodb adapter for you as well, then!:

https://www.npmjs.com/package/@next-auth/mongodb-adapter

It's a PR, but I hope to merge it soon:
nextauthjs/adapters#193

@Patryks1
Copy link
Contributor Author

Patryks1 commented Aug 29, 2021

Here is a pure mongodb adapter for you as well, then!:

https://www.npmjs.com/package/@next-auth/mongodb-adapter

It's a PR, but I hope to merge it soon:
nextauthjs/adapters#193

Unfortunately does not seem to work with pReact, Seems like the sessionContext wont accept the session being undefined when the user is logged out.

This is the error for more detail

Server Error
TypeError: Cannot read property 'SessionProvider' of undefined

This error happened while generating the page. Any console logs will be displayed in the terminal window.


  39 | <ReduxProvider store={store}>
  40 |   <PersistGate loading={null} persistor={persistor}>
> 41 |     <SessionProvider session={pageProps.session}>
     |     ^
  42 |       <Layout>
  43 |         <DefaultSeo
  44 |           openGraph={{
TypeError: Cannot read property 'SessionProvider' of undefined
    at Object.App (C:\Users\\.next\server\pages\_app.js:6399:137)
    at m (C:\Users\node_modules\preact-render-to-string\dist\commonjs.js:1:2523)
    at m (C:\Users\node_modules\preact-render-to-string\dist\commonjs.js:1:2667)
    at m (C:\Users\node_modules\preact-render-to-string\dist\commonjs.js:1:2667)
    at m (C:\Users\node_modules\preact-render-to-string\dist\commonjs.js:1:2667)
    at m (C:\Users\node_modules\preact-render-to-string\dist\commonjs.js:1:2667)
    at m (C:\Users\node_modules\preact-render-to-string\dist\commonjs.js:1:2667)
    at m (C:\Users\node_modules\preact-render-to-string\dist\commonjs.js:1:2667)
    at y (C:\Users\node_modules\preact-render-to-string\dist\commonjs.js:1:1278)
    at Object.renderPage (C:\Users\node_modules\next\dist\server\render.js:626:31)
    at Function.getInitialProps (C:\Users\.next\server\pages\_document.js:614:19)
    at Function.getInitialProps (C:\Users\P.next\server\pages\_document.js:1158:85)
    at Object.loadGetInitialProps (C:\Users\\node_modules\next\dist\shared\lib\utils.js:68:29)
    at Object.renderToHTML (C:\Users\node_modules\next\dist\server\render.js:643:40)
    at async doRender (C:\Users\node_modules\next\dist\server\next-server.js:1127:38)
    at async C:\Users\node_modules\next\dist\server\next-server.js:1221:28

It works fine when i disable pReact. The setup is identical to the one in the codesandbox

@balazsorban44
Copy link
Member

balazsorban44 commented Aug 29, 2021

The error you are seeing is because SessionProvider is not imported correctly, it has nothing to do with the session value being undefined.

Make sure that you have exactly this in your package.json:
next-auth: "4.0.0-next.24"

And you use the import next-auth/react in your _app file.

@Patryks1
Copy link
Contributor Author

Patryks1 commented Aug 29, 2021

The error you are seeing is because SessionProvider is not imported correctly, it has nothing to do with the session value being undefined.

Make sure that you have exactly this in your package.json:
next-auth: "4.0.0-next.24"

And you use the import next-auth/react in your _app file.

Yeah i updated my code with the docs you sent over, Ive cleared all yarn, npm locks + cache as well as deleted node_modules and .next same issue so i dont think its related to my env. Ill update the code sandbox to replicate the issue.

EDIT:
also like i mentioned if i disabled pReact it renders the page fine.

package.json

  "dependencies": {
    "@mongoosejs/double": "^0.2.0",
    "@next-auth/mongodb-adapter": "^0.0.2-pr.193-6071c497.276",
    "@reduxjs/toolkit": "^1.6.1",
    "@tailwindcss/forms": "^0.3.2",
    "@tailwindui/react": "^0.1.1",
    "bcryptjs": "^2.4.3",
    "coinbase-commerce-node": "^1.0.4",
    "cookies": "^0.8.0",
    "ioredis": "^4.27.5",
    "mongodb": "^4.1.1",
    "mongoose": "^5.12.7",
    "mongoose-unique-validator": "^2.0.3",
    "next": "11.1.0",
    "next-auth": "4.0.0-next.24",
    "next-images": "^1.7.0",
    "next-plugin-preact": "3.0.6",
    "next-seo": "^4.26.0",
    "next-swagger-doc": "^0.1.8",
    "preact": "10.5.14",
    "preact-render-to-string": "5.1.19",
    "preact-ssr-prepass": "1.2.0",
    "react": "npm:@preact/compat@0.0.4",
    "react-dom": "npm:@preact/compat@0.0.4",
    "react-icons": "^4.2.0",
    "react-multi-carousel": "^2.6.3",
    "react-redux": "^7.2.4",
    "redux-persist": "^6.0.0",
    "swr": "^0.5.6"
  },

_app.tsx

import Layout from '../components/Layout';
import { store } from '../redux/store';
import '../styles/globals.css';
import * as gtag from '../util/gtag';
import { NextPage } from 'next';

                        import { SessionProvider } from 'next-auth/react';

import { DefaultSeo } from 'next-seo';
import type { AppProps } from 'next/app';
import { useRouter } from 'next/router';
import React, { useEffect } from 'react';
import { Provider as ReduxProvider } from 'react-redux';
import { persistStore } from 'redux-persist';
import { PersistGate } from 'redux-persist/integration/react';

const App: NextPage<AppProps> = ({ Component, pageProps }) => {
  const router = useRouter();
  const persistor = persistStore(store);

  useEffect(() => {
    const handleRouteChange = (url: string): void => {
      gtag.pageview(url);
    };

    router.events.on('routeChangeComplete', handleRouteChange);

    return () => {
      router.events.off('routeChangeComplete', handleRouteChange);
    };
  }, [router.events]);

  return (
      <ReduxProvider store={store}>
        <PersistGate loading={null} persistor={persistor}>
            <SessionProvider session={pageProps.session}>
                  <Layout>
                    <Component {...pageProps} />
                  </Layout>
            </SessionProvider>
        </PersistGate>
      </ReduxProvider>
  );
};

@balazsorban44
Copy link
Member

Thank you, updating the CodeSandbox will be very helpful! 🙏 I'll look into it once you have it.

@Patryks1
Copy link
Contributor Author

Thank you, updating the CodeSandbox will be very helpful! 🙏 I'll look into it once you have it.

Here is the sandbox with the same issue maybe you can spot something - https://codesandbox.io/s/gracious-night-s346g?file=/next.config.js

@balazsorban44
Copy link
Member

I was able to verify that the problem is with next-plugin-preact. Simply removing it in next.config.js resolves the issue. I will try to dig into this and see if we have to make some adjustments to our bundling or is it a next-plugin-preact bug.

@balazsorban44
Copy link
Member

balazsorban44 commented Aug 29, 2021

So I did test out our PR #2552 that rewrites the core to TypeScript (and also changes the build process quite a bit), and actually, it resolves the problem without more changes!

If you want to give it a try: next-auth@0.0.0-pr.2552.f73a37a5

Keep in mind, this is still a work in progress. When merged though, your issue here should be resolved.

If you don't like to "live on the edge", I suggest you wait a few days/weeks for us to get the new release over the finish line. 🙂 Hope that helps!

@balazsorban44 balazsorban44 added bug Something isn't working adapters Changes related to the core code concerning database adapters and removed question Ask how to do something or how something works labels Aug 29, 2021
@Patryks1
Copy link
Contributor Author

So I did test out our PR #2552 that rewrites the core to TypeScript (and also changes the build process quite a bit), and actually, it resolves the problem without more changes!

If you want to give it a try: next-auth@0.0.0-pr.2552.f73a37a5

Keep in mind, this is still a work in progress. When merged though, your issue here should be resolved.

If you don't like to "live on the edge", I suggest you wait a few days/weeks for us to get the new release over the finish line. 🙂 Hope that helps!

Im down to live on the edge for a while :), That PR does seem to fix the SessionProvider issue however it seems like the google provider does not work.

[...nextauth].js

import { MongoDBAdapter } from '@next-auth/mongodb-adapter';
import { MongoClient, ObjectId } from 'mongodb';
import NextAuth from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';

const client = new MongoClient('mongodb://127.0.0.1:27017');

export default NextAuth({
 providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_ID,
      clientSecret: process.env.GOOGLE_SECRET,
    }),
    //TODO: Add Discord and Facebook
  ],
   session: {
     jwt: true,
     maxAge: 30 * 24 * 60 * 60, // 30 days
  },
  debug: process.env.DEBUG_NEXTAUTH === 'true',
  secret: process.env.NEXT_SECRET,

  // TODO: TS interface in types.d.ts is incorrect for JWT options needs to be corrected. 
  jwt: {
    // openssl rand -base64 64
    secret: process.env.JWT_SECRET,
    // jose newkey -s 512 -t oct -a HS512
    signingKey: {
      kty: 'oct',
      kid: '',
      alg: 'HS512',
      k: '',
    },
    verificationOptions: {
      algorithms: ['HS256'],
    },
    encryption: true,
    // You can generate an encryption key by using `npx node-jose-tools newkey -s 256 -t oct -a A256GCM -u enc`
    encryptionKey: process.env.JWT_ENCRYPTION_KEY,
    decryptionKey: process.env.JWT_ENCRYPTION_KEY,
    decryptionOptions: {
      algorithms: ['A256GCM'],
    },
    adapter: MongoDBAdapter({
      db: () => client.db('db'),
      ObjectId,
    }),
});

Error

https://next-auth.js.org/errors#signin_oauth_error Unexpected token o in JSON at position 1 {
  error: {
    message: 'Unexpected token o in JSON at position 1',
    stack: 'SyntaxError: Unexpected token o in JSON at position 1\n' +
      '    at JSON.parse (<anonymous>)\n' +
      '    at Object.encode (C:\\Users\\Pat\\Documents\\GitHub\\Pcific-Nextjs\\.next\\server\\pages\\api\\auth\\[...nextauth].js:163:65)\n' +
      '    at createPKCE (C:\\Users\\Pat\\Documents\\GitHub\\Pcific-Nextjs\\.next\\server\\pages\\api\\auth\\[...nextauth].js:1977:43)\n' +
      '    at getAuthorizationUrl (C:\\Users\\Pat\\Documents\\GitHub\\Pcific-Nextjs\\.next\\server\\pages\\api\\auth\\[...nextauth].js:1623:52)\n' +
      '    at runMicrotasks (<anonymous>)\n' +
      '    at processTicksAndRejections (internal/process/task_queues.js:95:5)\n' +
      '    at async Object.signin (C:\\Users\\Pat\\Documents\\GitHub\\Pcific-Nextjs\\.next\\server\\pages\\api\\auth\\[...nextauth].js:3155:32)\n' +
      '    at async NextAuthHandler (C:\\Users\\Pat\\Documents\\GitHub\\Pcific-Nextjs\\.next\\server\\pages\\api\\auth\\[...nextauth].js:868:18)\n' +
      '    at async C:\\Users\\Pat\\Documents\\GitHub\\Pcific-Nextjs\\.next\\server\\pages\\api\\auth\\[...nextauth].js:917:32\n' +
      '    at async Object.apiResolver (C:\\Users\\Pat\\Documents\\GitHub\\Pcific-Nextjs\\node_modules\\next\\dist\\server\\api-utils.js:101:9)\n' +
      '    at async DevServer.handleApiRequest (C:\\Users\\Pat\\Documents\\GitHub\\Pcific-Nextjs\\node_modules\\next\\dist\\server\\next-server.js:760:9)\n' +
      '    at async Object.fn (C:\\Users\\Pat\\Documents\\GitHub\\Pcific-Nextjs\\node_modules\\next\\dist\\server\\next-server.js:651:37)\n' +
      '    at async Router.execute (C:\\Users\\Pat\\Documents\\GitHub\\Pcific-Nextjs\\node_modules\\next\\dist\\server\\router.js:205:32)\n' +
      '    at async DevServer.run (C:\\Users\\Pat\\Documents\\GitHub\\Pcific-Nextjs\\node_modules\\next\\dist\\server\\next-server.js:825:29)\n' +
      '    at async DevServer.handleRequest (C:\\Users\\Pat\\Documents\\GitHub\\Pcific-Nextjs\\node_modules\\next\\dist\\server\\next-server.js:292:20)',
    name: 'SyntaxError'
  },
  provider: {
    id: 'google',
    name: 'Google',
    type: 'oauth',
    wellKnown: 'https://accounts.google.com/.well-known/openid-configuration',
    authorization: { params: [Object] },
    idToken: true,
    checks: [ 'pkce', 'state' ],
    profile: [Function: profile],
    signinUrl: 'http://localhost:3000/api/auth/signin/google',
    callbackUrl: 'http://localhost:3000/api/auth/callback/google',
    clientId: '',
    clientSecret: ''
  },
  message: 'Unexpected token o in JSON at position 1'
}

Sign in function

onClick={() =>
              signIn('google', {
                callbackUrl: `${window.location.origin}/`,
              })
            }

@balazsorban44
Copy link
Member

signingKey is supposed to be a string, you provided it as an object.

next-auth/src/lib/jwt.js

Lines 33 to 35 in 08349c3

const _signingKey = signingKey
? jose.JWK.asKey(JSON.parse(signingKey))
: getDerivedSigningKey(secret)

You are right about the jwt types, there is an issue related to it #2597

@Patryks1
Copy link
Contributor Author

Patryks1 commented Aug 29, 2021

signingKey is supposed to be a string, you provided it as an object.

next-auth/src/lib/jwt.js

Lines 33 to 35 in 08349c3

const _signingKey = signingKey
? jose.JWK.asKey(JSON.parse(signingKey))
: getDerivedSigningKey(secret)

You are right about the jwt types, there is an issue related to it #2597

I dont think the mongo adapter is working, the google call is successful now as the JWT is no longer failing. however when it calls getUserByAccount it absolutely spams my termal with it and exits the application.

The OAUTH_CALLBACK_RESPONSE seems correct with all the data.

one more seems like useSession is requesting options parameter can this be changed to optional, In index.d.ts its required atm.

same [...nextauth].js config as above, just without JWT bit.

[next-auth][debug][adapter_getUserByAccount] {
  args: [
    { providerAccountId: 'ACCID', provider: 'google' }
  ]
}

@balazsorban44
Copy link
Member

could you share what you mean by spamming your terminal? I tried myself locally and although didn't use the Google Provider specifically, it did seem to work.

@Patryks1
Copy link
Contributor Author

could you share what you mean by spamming your terminal? I tried myself locally and although didn't use the Google Provider specifically, it did seem to work.

All it does is spam the getuserbyaccount posted above in terminal. Before it just displays what Google pauth returns with all of the correct data. Seems like the dB and tables don't get created in mongodb

@balazsorban44
Copy link
Member

What do you mean by spamming specifically? Could you please paste anything printed to the terminal? It might be very helpful information there.

@Patryks1
Copy link
Contributor Author

What do you mean by spamming specifically? Could you please paste anything printed to the terminal? It might be very helpful information there.

I dont know if i explaied it wrong or not but it literally just spams the

[next-auth][debug][adapter_getUserByAccount] {
  args: [
    { providerAccountId: 'ACCID', provider: 'google' }
  ]
}

as if it was trying to call the function again if it fails causing the app to exit right after too many calls where made.

here is a pic -

First
Second
Third

@balazsorban44
Copy link
Member

That is strange, I don't have an explanation. There is no retry mechanism anywhere in the core or the adapter. I'll try to reproduce it locally.

@balazsorban44
Copy link
Member

balazsorban44 commented Sep 2, 2021

@Patryks1 I reproduced it locally, will investigate now!

UPDATE:
I identified the problem, it wasn't related to the new adapter, actually. It was in core. Should be fixed in next-auth@4.0.0-next.26. Could you give it a try?

@Patryks1
Copy link
Contributor Author

Patryks1 commented Sep 3, 2021

@Patryks1 I reproduced it locally, will investigate now!

UPDATE:
I identified the problem, it wasn't related to the new adapter, actually. It was in core. Should be fixed in next-auth@4.0.0-next.26. Could you give it a try?

I think you released the wrong version (seems like its main branch not next), But weirdly enough it does work haha.

@balazsorban44
Copy link
Member

balazsorban44 commented Sep 3, 2021

Not sure what you mean, here it is on npm
https://www.npmjs.com/package/next-auth/v/4.0.0-next.26

it's on the next channel currently.

@Patryks1
Copy link
Contributor Author

Patryks1 commented Sep 3, 2021

Not sure what you mean, here it is on npm
https://www.npmjs.com/package/next-auth/v/4.0.0-next.26

it's on the next channel currently.

Not sure if i am missing something but in the 4.0.0-next.24 i had to change the useSession hooks, Session provider, next-auth/react does not exist and use the adapter instead of the DB. With 4.0.0-next.26 it seems to use the old structure.

@balazsorban44
Copy link
Member

That would be really surprising. You can verify here it's not the case 👀 https://unpkg.com/browse/next-auth@4.0.0-next.26/

@Patryks1
Copy link
Contributor Author

Patryks1 commented Sep 3, 2021

That would be really surprising. You can verify here it's not the case 👀 https://unpkg.com/browse/next-auth@4.0.0-next.26/

Seems like it was an yarn issue, using NPM fetched the correct build. Weird how 3.29.0 gives me the mongo dependency issue but if i use 4.0.0-next.26 with yarn it fetches the wrong build but that works fine with preact.

any ways with the actual 4.0.0-next.26 and mongoDbAdapter does the client need to be connected? if so do you have any recommendations how to go about that as i am getting the following.

MongoError: MongoClient must be connected before calling MongoClient.prototype.db

@balazsorban44
Copy link
Member

Yes, hoping to get the adapter PR merged this weekend. until then, check this page:

https://github.com/nextauthjs/adapters/blob/3c949284ad458271a3d12e2eefcfa0cc2581f804/packages/mongodb/README.md

@Patryks1
Copy link
Contributor Author

Patryks1 commented Sep 3, 2021

Yes, hoping to get the adapter PR merged this weekend. until then, check this page:

https://github.com/nextauthjs/adapters/blob/3c949284ad458271a3d12e2eefcfa0cc2581f804/packages/mongodb/README.md

Brilliant it worked :).
Is

export type RedirectableProvider = "email" | "credentials"

Intended? I use google, fb and discord, I can use them as a provider just fine but ofc typescript will complain. Could this be changes to the old one -

export type RedirectableProvider = "email" | "credentials"

export type SignInProvider = RedirectableProvider | string | undefined

@balazsorban44
Copy link
Member

Awesome! Happy to accept a PR that I can check out locally. let's open a different issue. Sounds like the original problem here is solved! 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
adapters Changes related to the core code concerning database adapters bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants