nextauthjs / next-auth

Authentication for the Web.
https://authjs.dev
ISC License
22.87k stars 3.08k forks source link

Jwt generated is not signed #10933

Open cmprojectcm opened 4 weeks ago

cmprojectcm commented 4 weeks ago

Environment

  System:
    OS: Windows 11 10.0.22631
    CPU: (8) x64 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
    Memory: 15.44 GB / 31.66 GB
  Binaries:
    Node: 20.12.1 - C:\Program Files\nodejs\node.EXE
    npm: 10.5.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Chromium (123.0.2420.97)
    Internet Explorer: 11.0.22621.1
  npmPackages:
    next: 14.2.3 => 14.2.3 
    next-auth: ^5.0.0-beta.17 => 5.0.0-beta.18 
    react: ^18 => 18.3.1 

Reproduction URL

https://github.com/cmprojectcm/test-nextjs

Describe the issue

jwt token generated is not signed. If I use it on jwt.io it shows is not signed.

Also If I try sign it with Jwt.sign() method jsonwebtoken library, inside callbacks I get auth error.

Furthermpore since this library it helps for using providers, which in my case am using Keycloak. We need to have the option to use Keycloak's access_token as the token for the session

How to reproduce

auth.js:

import NextAuth from "next-auth";
import keycloak from "next-auth/providers/keycloak";
import Jwt from "jsonwebtoken";
import { hkdf } from "crypto";
export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [keycloak],
  session: {
    strategy: "jwt",
    maxAge: 4 * 60 * 60,
    updateAge: 3 * 60 * 60,
  },
  callbacks: {
    session({ session, token, user }) {
      session.user.id = token.id;
      session.user.roles = token?.roles;
      return session;
    },
    async jwt({ token, user, account, profile }) {
      if (user) {
        token.id = user.id;
      }
      if (account) {
        if (account.access_token) {
          let decodedToken = Jwt.decode(account.access_token || "");
          token.roles = decodedToken?.realm_access?.roles;
        }
      }
      return token;
    },
  },
});

auth.js with signedToken:

import NextAuth from "next-auth";
import keycloak from "next-auth/providers/keycloak";
import Jwt from "jsonwebtoken";
import { hkdf } from "crypto";
export const { handlers, signIn, signOut, auth } = NextAuth({
  providers: [keycloak],
  session: {
    strategy: "jwt",
    maxAge: 4 * 60 * 60,
    updateAge: 3 * 60 * 60,
  },
  callbacks: {
    session({ session, token, user }) {
      session.user.id = token.id;
      session.user.roles = token?.roles;
      return session;
    },
    async jwt({ token, user, account, profile }) {
      if (user) {
        token.id = user.id;
      }
      if (account) {
        if (account.access_token) {
          let decodedToken = Jwt.decode(account.access_token || "");
          token.roles = decodedToken?.realm_access?.roles;
        }
      }

      const signedToken = Jwt.sign(
        token,
        "Xq5gBf6r0YIS/3HBuWAEMwCci5s1SdpTVvNLHu3Ykak8"
      );

      return signedToken;
    },
  },
});

Expected behavior

jwt should be automatically signed, and the token should be decoded successfully on jwt.io

Furthermore, since this library it helps for using providers, which in my case am using Keycloak. We need to have the option to use Keycloak's access_token as the token for the session