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

withMiddlewareAuthRequired doesn't check if access token has expired #1723

Open
6 tasks done
jln13x opened this issue Apr 5, 2024 · 4 comments
Open
6 tasks done

withMiddlewareAuthRequired doesn't check if access token has expired #1723

jln13x opened this issue Apr 5, 2024 · 4 comments

Comments

@jln13x
Copy link

jln13x commented Apr 5, 2024

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

@jln13x jln13x changed the title withMiddlewareAuthRequired withMiddlewareAuthRequired doesn't check if access token has expired Apr 5, 2024
@jln13x
Copy link
Author

jln13x commented Apr 6, 2024

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).*)"],
};

@bashaus
Copy link

bashaus commented Apr 16, 2024

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

@jln13x
Copy link
Author

jln13x commented Apr 17, 2024

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

@bashaus
Copy link

bashaus commented Apr 25, 2024

@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;
    }
  },
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants