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

[JWT] Using database still uses JWT strategy and gives a JWTSessionError #11510

Closed
abdulahd2008 opened this issue Aug 3, 2024 · 7 comments
Closed
Labels
bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.

Comments

@abdulahd2008
Copy link

Environment

Package Info: 
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "next": "14.2.5",
    "next-auth": "^5.0.0-beta.20",
    "drizzle-orm": "^0.32.1",
    
Node Version: v20.12.2
OS: Fedora Linux
Browser: Firefox 

Reproduction URL

https://github.com/A1X5H04/notesync-web

Describe the issue

I am getting the following JWT Session Error when using a database strategy, this only occurs when using a database strategy,

auth.ts

import NextAuth from "next-auth";
import authConfig from "./auth.config";
import { DrizzleAdapter } from "@auth/drizzle-adapter";
import db from "./lib/db";

export const { handlers, signIn, signOut, auth } = NextAuth({
  adapter: DrizzleAdapter(db),
  pages: {
    signIn: "/auth/login",
    error: "/auth/error",
  },
  secret: "wnlAmKEdpTw+OY1L6PIk5ALNzHAKTqW23wdVpIjuKf",
  callbacks: {
    jwt({ token, user }) {
      if (user) token.sub = user.id;
      return token;
    },
    session({ session, token }) {
      if (token.sub) session.user.id = token.sub;
      return session;
    },
  },
  debug: true,
  ...authConfig,
});

auth.config.ts

import GitHub from "next-auth/providers/github";
import Credentials from "next-auth/providers/credentials";
import type { NextAuthConfig } from "next-auth";
import credentials from "next-auth/providers/credentials";
import { loginSchema } from "./lib/form-schemas";
import { getUserByEmail } from "./queries/user";
import bcryptjs from "bcryptjs";

// Notice this is only an object, not a full Auth.js instance

export default {
  providers: [GitHub],
} satisfies NextAuthConfig;

Here's the error I am getting:

GET /api/auth/callback/github?code=779*******7f58895f6b 302 in 12162ms
[auth][error] JWTSessionError: Read more at https://errors.authjs.dev#jwtsessionerror
[auth][cause]: JWEInvalid: Invalid Compact JWE
at compactDecrypt (webpack-internal:///(middleware)/./node_modules/jose/dist/browser/jwe/compact/decrypt.js:20:15)
at jwtDecrypt (webpack-internal:///(middleware)/./node_modules/jose/dist/browser/jwt/decrypt.js:12:100)
at Object.decode (webpack-internal:///(middleware)/./node_modules/@auth/core/jwt.js:81:79)
at Module.session (webpack-internal:///(middleware)/./node_modules/@auth/core/lib/actions/session.js:23:39)
at AuthInternal (webpack-internal:///(middleware)/./node_modules/@auth/core/lib/index.js:47:77)
at async Auth (webpack-internal:///(middleware)/./node_modules/@auth/core/index.js:126:34)
at async handleAuth (webpack-internal:///(middleware)/./node_modules/next-auth/lib/index.js:136:29)
at async adapter (webpack-internal:///(middleware)/./node_modules/next/dist/esm/server/web/adapter.js:179:16)
at async /mnt/data/Projects/Web Projects/notisync-web/node_modules/next/dist/server/web/sandbox/sandbox.js:110:22
at async runWithTaggedErrors (/mnt/data/Projects/Web Projects/notisync-web/node_modules/next/dist/server/web/sandbox/sandbox.js:107:9)
[auth][details]: {}

And yes, I don't have malformed secret configured, and I also have pass a string from the .env to the secret key in auth config, I have also not touched any jwt function in the library

How to reproduce

  • Create a next app with npx create@next-app
  • Install necessary libraries, here I install next-auth@beta and drizzle for database orm
  • Follow the next auth documentation to configure next auth in nextjs project
  • Follow the documentation for the database adapter and configure them as well
  • Finally follow the edge compatibilty documentation for the next auth middleware since it works on edge
  • Configure the ouath providers and run the app
  • Invoke the oauth provider function and authenticate your app with oauth provider once done you will be thrown the error

Expected behavior

Should create a session in the database and authenticate the user and redirect them to designated route, without any error, and should use database approach

@abdulahd2008 abdulahd2008 added bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime. labels Aug 3, 2024
@Waylon-Firework
Copy link

image I got the same error

@Waylon-Firework

This comment was marked as off-topic.

@balazsorban44
Copy link
Member

balazsorban44 commented Aug 8, 2024

Hi, the code snippet/reproduction does not match fully, as in #11510 (comment), auth.ts does not have the strategy: "jwt" set, while the repro does.

Judging from this, the problem is that outside Middleware, you expect to use database sessions, while inside, you expect to use JWT sessions. The two cannot be used at the same time.

The database session strategy creates a session cookie that is not a valid JWE, hence the error being thrown.

So this is expected.

@abdulahd2008
Copy link
Author

Hi, the code snippet/reproduction does not match fully, as in #11510 (comment), auth.ts does not have the strategy: "jwt" set, while the repro does.

Judging from this, the problem is that outside Middleware, you expect to use database sessions, while inside, you expect to use JWT sessions. The two cannot be used at the same time.

The database session strategy creates a session cookie that is not a valid JWE, hence the error being thrown.

So this is expected.

I used it to get rid of the error, I followed this documentation for edge compatibility, I want it to just have the database strategy not jwt altogether, What I did wrong ?

@SaddamMohsen
Copy link

you must remove jwt callback function
and add strategy:"database"
from auth.ts file

@taxx0r
Copy link

taxx0r commented Aug 19, 2024

I have the same problem. I'm using the split config from here and not using edge

Changing session: { strategy: "jwt" } to session: { strategy: "database" }

auth.config.ts

import Discord from "next-auth/providers/discord"
import type { NextAuthConfig } from "next-auth"
 
// Notice this is only an object, not a full Auth.js instance
export default {
  providers: [Discord],
} satisfies NextAuthConfig

auth.ts

import NextAuth from "next-auth"
import authConfig from "./auth.config"
 
import { PrismaClient } from "@prisma/client"
import { PrismaAdapter } from "@auth/prisma-adapter"
 
const prisma = new PrismaClient()
 
export const { handlers, auth, signIn, signOut } = NextAuth({
  adapter: PrismaAdapter(prisma),
  session: { strategy: "database" },
  callbacks: {
    session({ session, user }) {
        if (user && user.role) {
            session.user.role = user.role    
        }
        
        return session
    }
  },
  ...authConfig,
})

middleware.ts

import NextAuth from "next-auth"
import authConfig from "./auth.config"
 
export const { auth: middleware } = NextAuth(authConfig)

The code works and recover the role property from database, but previously show this error in console

GET /api/auth/callback/discord?code=xxxxxxxx 302 in 1219ms
[auth][error] JWTSessionError: Read more at https://errors.authjs.dev#jwtsessionerror
[auth][cause]: JWEInvalid: Invalid Compact JWE
    at compactDecrypt (webpack-internal:///(middleware)/./node_modules/.pnpm/[email protected]/node_modules/jose/dist/browser/jwe/compact/decrypt.js:20:15)
    at jwtDecrypt (webpack-internal:///(middleware)/./node_modules/.pnpm/[email protected]/node_modules/jose/dist/browser/jwt/decrypt.js:12:100)
    at Object.decode (webpack-internal:///(middleware)/./node_modules/.pnpm/@[email protected]/node_modules/@auth/core/jwt.js:81:79)
    at Module.session (webpack-internal:///(middleware)/./node_modules/.pnpm/@[email protected]/node_modules/@auth/core/lib/actions/session.js:23:39)
    at AuthInternal (webpack-internal:///(middleware)/./node_modules/.pnpm/@[email protected]/node_modules/@auth/core/lib/index.js:47:77)
    at async Auth (webpack-internal:///(middleware)/./node_modules/.pnpm/@[email protected]/node_modules/@auth/core/index.js:126:34)
    at async handleAuth (webpack-internal:///(middleware)/./node_modules/.pnpm/[email protected][email protected][email protected][email protected][email protected][email protected]/node_modules/next-auth/lib/index.js:136:29)
    at async adapter (webpack-internal:///(middleware)/./node_modules/.pnpm/[email protected][email protected][email protected][email protected]/node_modules/next/dist/esm/server/web/adapter.js:179:16)
    at async /Users/luis/Documents/NextJS/tetrisstudio/node_modules/.pnpm/[email protected][email protected][email protected][email protected]/node_modules/next/dist/server/web/sandbox/sandbox.js:110:22
    at async runWithTaggedErrors (/Users/luis/Documents/NextJS/tetrisstudio/node_modules/.pnpm/[email protected][email protected][email protected][email protected]/node_modules/next/dist/server/web/sandbox/sandbox.js:107:9)

@mrtanatorn44
Copy link

In my case I got less error detail from JWTSessionError because I try to access null object.
So I hope this can help anyone get less error detail like me.

Entire error I got

 [JWTSessionError: Read more at https://errors.authjs.dev#jwtsessionerror] {
  name: 'JWTSessionError',
  type: 'JWTSessionError',
  kind: 'error',
  message: 'Read more at https://errors.authjs.dev#jwtsessionerror'
} []

"next": "15.0.3",
"next-auth": "^5.0.0-beta.25",
auth.js

import NextAuth from "next-auth";
import ... from "next-auth/providers/...";

// @see https://authjs.dev/getting-started/authentication/oauth
export const { auth, handlers, signIn, signOut } = NextAuth({
  providers: [
   ...
  ],
  ...
  session: {
    strategy: "jwt",
  },
  callbacks: {
    async jwt({
      token,
      account,
      profile,
    }: {
      token: any;
      account: any;
      profile?: any;
    }) {
      if (account) {
        token.accessToken = account.access_token;
        token.profile = profile;
      }
      return token;
    },
    async session({ session, token }: { session: any; token: any; }) {
      return {
        user: {
          company: token.profile.company, // <----------------- company var is null, cause JWTSessionError 
        },
        ...
      };
    },
    authorized: async ({ auth }) => {
      return !!auth;
    },
  },
  pages: {
    ...
  },
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working triage Unseen or unconfirmed by a maintainer yet. Provide extra information in the meantime.
Projects
None yet
Development

No branches or pull requests

6 participants