NextAuth, NextJS - getToken always return null in middleware function
Asked Answered
H

2

6

ENVIROMENT


  • NextJS: 12.2.2
  • NextAuth: 4.10.3 (latest)
    • Provider: Credentials
  • Browser: Google Chrome
  • Node: LTS

ISSUE


Hello everyone

I'm using NextAuth for authentication with credentials provider and strategy jwt, but function getToken is always return null in my middleware, while my jwt callback in NextAuthOptions not return null

I checked token in cookie storage and trying decode token, result decode is still right

Variable enviroment NEXTAUTH_SECRET was added in file .env.local

CODE


src/page/api/auth/[...nextauth].ts

export const decode = async (data: any) => {
  const { secret, token } = data;
  const verify = jwt.verify(token, secret) as JWT;
  return verify;
};
export const encode = async (data: any) => {
  const { secret, token } = data;

  const payload = {
    username: token.username,
    email: token.email,
    _id: token._id,
  };
  const accessToken = jwt.sign(payload, secret, {
    expiresIn: '1209600s',
    algorithm: 'HS512',
  });
  return accessToken;
};

export const authOptions: NextAuthOptions = {
  providers: [
    CredentialsProvider({
      type: 'credentials',
      credentials: {},
      async authorize(credentials: any, req) {
        const { username, password } = credentials as {
          username: string;
          password: string;
        };

        try {
          const { data } = await client.mutate({
            mutation: login,
            variables: {
              userInput: {
                username,
                password,
              },
            },
          });

          const { user } = data.login;

          const response = {
            username: user.username,
            email: user.email,
            _id: user._id,
          };
          return response;
        } catch (error) {
          throw new Error('Unauthorized');
        }
      },
    }),
  ],
  session: {
    strategy: 'jwt',
    maxAge: 60 * 60 * 24 * 14,
  },
  jwt: {
    maxAge: 60 * 60 * 24 * 14,
    secret: process.env.SECRET,
    encode: encode,
    decode: decode,
  },
  pages: {
    signIn: '/auth/login',
    signOut: '/logout',
    error: '/auth/login',
    newUser: '/auth/register',
    verifyRequest: '/auth/verify',
  },
  callbacks: {
    async signIn({ user }) {
      return user ? true : false;
    },
    async session({ session, token }) {
      session.username = token.username;
      session.email = token.email;
      session._id = token._id;
      session.user!.name = token.username as string;
      session.user!.email = token.email as string;
      return session;
    },
    async jwt({ token, user }) {
      if (user?.username) {
        token.username = user.username;
        token.email = user.email;
        token._id = user._id;
      }

      return token;
    },
  },
};
export default NextAuth(authOptions);

src/middleware.ts

export default withAuth(function middleware(req: NextRequest) {}, {
  callbacks: {
    authorized: function ({ token }) {
      console.log(token); // token is always null

      return true;
    },
  },
});

export const config = { matcher: ['/chat', '/notifications'] };
Haro answered 10/8, 2022 at 6:26 Comment(0)
B
4

Hey there had the same issue, updating to [email protected], as mentioned here, fixed it.

Beseech answered 12/8, 2022 at 20:28 Comment(3)
The whole discussion is useless in my case I am using Next 13.1.2 and this issue is still a nightmareMol
@Mol did you figure this out? I have the same issueNicolis
@TylerPashigian I couldn't find solution I had to create a Wrapper component on the frontend to the block pages from unauthorised access.Mol
C
0

you should remove the secret option inside the jwt and put it outside. you should ensure you only have one secret value. it work for me on NextJs 13.4.12, the code should look like :

    secret: process.env.NEXTAUTH_SECRET,
    callbacks: {
    async jwt({ token, user }) {
      if (user) {
        token = {
          ...token,
          id: user.id,
          //@ts-ignore
          role: user?.role,
          //@ts-ignore
          name: user?.fullName,
          //@ts-ignore
          picture: user?.avatar,
        };
        
        return token;
      }
      return token;
    },
    async session({ session, token }) {
    //@ts-ignore
      session.user.role = token.role;
      //@ts-ignore
      session.user.image = token.picture;
      //@ts-ignore
      session.user.name = token.name;


      return session;
    },
  },

Catholicize answered 30/8, 2023 at 14:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.