auth0 / nextjs-auth0

Next.js SDK for signing in with Auth0

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

withMiddlewareAuthRequired doesn't check if access token has expired

jln13x opened this issue Β· comments

Checklist

Description

The withMiddlewareAuthRequired doesn't seem to check if the access token is actually still valid

Reproduction

  • Add Middleware
  • Wait for Token to expire
  • Still have access

Additional context

No response

nextjs-auth0 version

3.5.0

Next.js version

14.1.3

Node.js version

v20.11.1

Had to add custom code to check for it. Isn't there a better way to do that?

import { logger } from "@/server/logger";
import { routes } from "@/shared/routes";
import { safeTryAsync } from "@/shared/safe-try";
import { getAccessToken, withMiddlewareAuthRequired } from "@auth0/nextjs-auth0/edge";
import type { NextMiddleware } from "next/server";
import { NextResponse } from "next/server";
import { pathToRegexp } from "path-to-regexp";

const publicRoutes: string[] = ["/api/auth/(.*)"];

const middleware: NextMiddleware = async (req, event) => {
  const publicRoutesAsRegex = publicRoutes.map((route) => pathToRegexp(route));

  const pathname = req.nextUrl.pathname;
  const isPublicRoute = publicRoutesAsRegex.some((route) => route.test(pathname));

  const tag = isPublicRoute ? "🌍" : "πŸ”“";
  console.log(`[${tag}] Middleware hit for ${pathname}`);

  if (isPublicRoute) {
    return NextResponse.next();
  }

  // Only seems to check if a session exists, not if it's valid - But atleast it extends the Cookie expiration
  return withMiddlewareAuthRequired({
    middleware: async (req) => {
      const res = NextResponse.next();
      const [, error] = await safeTryAsync(() => getAccessToken(req, res));

      if (error) {
        logger.error("Error getting access token", error);
        return NextResponse.redirect(new URL(routes.logout(), req.nextUrl));
      }

      return res;
    },
  })(req, event);
};

export default middleware;

export const config = {
  matcher: ["/((?!.+\\.[\\w]+$|_next).*)"],
};

Out of curiosity, do you also get the following error message:

nextjs-auth0 is attempting to set cookies from a server component,see https://github.com/auth0/nextjs-auth0#using-this-sdk-with-react-server-components

Out of curiosity, do you also get the following error message:

nextjs-auth0 is attempting to set cookies from a server component,see https://github.com/auth0/nextjs-auth0#using-this-sdk-with-react-server-components

ye but shouldnt be related

@jln13x – I implemented the same logic as your code, and it worked until I received the AccessTokenErrorCode ERR_EXPIRED_ACCESS_TOKEN. The problem was that the redirect was stuck in an infinite loop.

I solved it by updating the session to expire. This may not be the right way to do it (I know the documentation recommend against it), but I redirect to the logout URL afterwards to clean up the session:

import {
  AccessTokenError,
  getAccessToken,
  updateSession,
  withMiddlewareAuthRequired,
} from "@auth0/nextjs-auth0/edge";
import { NextResponse } from "next/server";

export default withMiddlewareAuthRequired({
  middleware: async function middleware(req) {
    try {
      await getAccessToken();
      return NextResponse.next();
    } catch (err) {
      if (err instanceof AccessTokenError) {
        const res = NextResponse.redirect(
          "https://www.example.com/api/auth/logout",
        );

        return updateSession(req, res, {
          user: [],
          accessToken: undefined,
          idToken: undefined,
          refreshToken: undefined,
          accessTokenExpiresAt: 0,
        });
      }

      /* Fallback: if you don't know how to handle the error */
      throw err;
    }
  },
});