question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Null token in middleware authorized callback

See original GitHub issue

Environment

System: OS: Linux 5.15 Ubuntu 20.04.4 LTS (Focal Fossa) CPU: (4) x64 Intel® Core™ i5-6200U CPU @ 2.30GHz Memory: 3.83 GB / 15.07 GB Container: Yes Shell: 5.0.17 - /bin/bash Binaries: Node: 16.13.0 - ~/.nvm/versions/node/v16.13.0/bin/node npm: 8.1.0 - ~/.nvm/versions/node/v16.13.0/bin/npm Browsers: Brave Browser: 104.1.42.88 Chrome: 104.0.5112.79 Firefox: 103.0 npmPackages: next: ^12.2.5 => 12.2.5 next-auth: 4.10.3 => 4.10.3 react: 18.2.0 => 18.2.0

Reproduction URL

https://github.com/Biratus/middleware-issue-reproducer

Describe the issue

The issue has been discussed but closed with next@12.2.5: https://github.com/nextauthjs/next-auth/issues/5008 which I have followed for the past couple weeks. However the issue is still occurring with next@12.2.5:

The middleware callback “authorized” receives a null value for the “token” property. I am using jwt strategy and credentials.

Here is the middleware code I use, pretty straightforward.


export default withAuth(
  // `withAuth` augments your `Request` with the user's token.
  function middleware(req) {
    console.log("middleware", req.nextauth.token);
  },
  {
    callbacks: {
      authorized: ({ req, token }) => {
        console.log("authorized "+req.nextUrl.pathname, token);
        if(req.nextUrl.pathname === '/private') {
          return !!token;
        }
        return true;// login or public
      },
    },
    pages: {
      signIn: "/login",
    },
  }
);
export const config = { matcher: ["/private","/public"] };

I linked a reproducer in which I added a description in the README There are 3 useful pages in the app:

  • /login: a button to sign in (no form)
  • /public: a public url which doesn’t need a token to be accessed
  • /private: a private url which requires a token/authentication to be accessed

I have included logs in the middleware.js file. In the authorized callback and middleware function. The /login page does sign in the user, we can see the token being created in the “storage” tab in the developer console. The /private page redirects to /login even when there is a token.

How to reproduce

Clear all cookies.

Go to login page: localhost:3000/login Click on the sign in button. Check that a token is added to cookies.

Navigate to localhost:3000/private

The sever logs shows: “authorized /private null” (authorized callback log)

Expected behavior

The /private page should be visible when a user is authenticated/when there is a token in cookies.

Warning: I am new to nextJS and NodeJS developpement in general. However I have had my fair share of Spring and JS dev. So there might be some things I don’t do correctly.

Thank you all for taking the time.

Issue Analytics

  • State:closed
  • Created a year ago
  • Reactions:1
  • Comments:21 (1 by maintainers)

github_iconTop GitHub Comments

9reactions
sklumcommented, Aug 26, 2022

I believe I’ve figured out my issue as well. In my case, I’m using the Next.js, EmailProvider, and the PrismaAdapter.

According to the session docs, the default strategy when using an adapter is "database". However, the Next.js caveats section notes that middleware:

Only supports the “jwt” session strategy. We need to wait until databases at the Edge become mature enough to ensure a fast experience. (If you know of an Edge-compatible database, we would like if you proposed a new Adapter)

I’m not sure if I’m accessing the token correctly now, but after setting session.strategy = "jwt" I have a working login flow. That is, in a new incognito session, if I navigate to localhost:3000/home I’m redirected to my custom signin page in which I can provide an email to send a magic link. Clicking on said link returns me to localhost:3000/home with a correct session object after making it past the middleware because the token is non-null. Without changing the strategy, the token in middleware.ts is always null as mentioned above.

Note that I didn’t need to do anything with process.env.NEXTAUTH_SECRET within NextAuthOptions itself. According to the secret docs:

If you set NEXTAUTH_SECRET as an environment variable, you don’t have to define this option.

For completeness, here’s the relevant code:

[...nextauth.ts]

import NextAuth, { NextAuthOptions } from "next-auth";
import EmailProvider from "next-auth/providers/email";
import { PrismaAdapter } from "@next-auth/prisma-adapter";
import { PrismaClient } from "@prisma/client";

const prisma = new PrismaClient();

export const authOptions: NextAuthOptions = {
  adapter: PrismaAdapter(prisma),
  providers: [
    EmailProvider({
      server: process.env.EMAIL_SERVER,
      from: process.env.EMAIL_FROM,
    }),
  ],
  pages: {
    signIn: "/signin",
  },
  session: {
    strategy: "jwt", // See https://next-auth.js.org/configuration/nextjs#caveats, middleware (currently) doesn't support the "database" strategy which is used by default when using an adapter (https://next-auth.js.org/configuration/options#session)
  },
};

export default NextAuth(authOptions);

[middleware.ts]

export { default } from "next-auth/middleware";

export const config = { matcher: ["/home"] };

Getting a null token is pretty opaque with respect to the underlying issue (assuming I’m doing things correctly now). It’d be nice if when attempting to using middleware with the "database" session strategy there was some sort of error / warning instead of failing in this way.

2reactions
jrandallwcommented, Aug 21, 2022

@ThangHuuVu I scaffolded a new app, have NEXTAUTH_SECRET defined and middleware still won’t work. Next 12.2.5 and NextAuth 4.10.3.

Read more comments on GitHub >

github_iconTop Results From Across the Web

NextAuth, NextJS - getToken always return null in middleware ...
Hey there had the same issue, updating to next@12.2.5 , as mentioned here, fixed it.
Read more >
Laravel Authentication: A Laravel Passport Tutorial - Toptal
Since tokens are generally used in API authentication, Laravel Passport provides an easy and secure way to implement token authorization on an OAuth...
Read more >
Persist additional claims and tokens from external providers in ...
An ASP.NET Core app can establish additional claims and tokens from external authentication providers, such as Facebook, Google, Microsoft, ...
Read more >
Auth0 Example Configuration — Daml SDK 2.1.1 documentation
Enter the name of the application, e.g. ex-daml-auth-middleware . ... Configure the allowed callback URLs: http://localhost:5000/auth/cb .
Read more >
Configuring Middleware for Authentication - Thinkster.io
The getTokenFromHeader() function is a helper function that both middlewares use to extract the JWT from the Authorization header. The only difference between ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found