Auth0 triggers auth/profile endpoint every few seconds. Is this expected behavior?

When I look to see what initiates the call, its the use-user.js hook within the Auth0 code. This is the code:

"use client";
import useSWR from "swr";
export function useUser() {
    const { data, error, isLoading } = useSWR(process.env.NEXT_PUBLIC_PROFILE_ROUTE || "/auth/profile", (...args) => fetch(...args).then((res) => {
        if (!res.ok) {
            throw new Error("Unauthorized");
        }
        return res.json();
    }));
    // if we have the user loaded via the provider, return it
    if (data) {
        return {
            user: data,
            isLoading: false,
            error: null
        };
    }
    if (error) {
        return {
            user: null,
            isLoading: false,
            error
        };
    }
    return {
        user: data,
        isLoading,
        error
    };
}

When I’m logged in it’s not really a problem. But when I’m not, it clogs up my logs with a 404 error. Is this expected behavior? The only thing I can think of is I set up my middleware wrong, but I followed the quick start.

import { NextRequest } from "next/server"
import { auth0 } from "./lib/auth0"

const GUEST_SECRET = process.env.GUEST_SECRET!
const secret = new TextEncoder().encode(GUEST_SECRET)

export async function middleware(request: NextRequest) {
  const response = await auth0.middleware(request)

  return response
}

export const config = {
  matcher: [
    "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
  ],
}

Hi @mmaccou

I am sorry about the delayed response to your inquiry!

Basically, if an user is not authenticated in your NextJS application, it should not be throwing 404 errors continually.

Are you redirecting to a proper auth endpoint as mentioned in this community post? Also, are you using loginWithRedirect() or loginWithPopup()? You could try to download our sample app and build upon it or replace parts and see if the behaviour is being reproduced.

Simply, I believe there might be a slight misconfiguration inside your application where it is not using a proper endpoint. You could examine the sample application and compare it with your own personal configuration.

If you have any other questions, let me know!

Kind Regards,
Nik

Hi Nik,

I’m not using loginWithRedirect() or loginWithPopup(). I’m I have a button that takes users to http://localhost:3000/auth/login. That works fine. And I double checked my settings and confirmed localhost is included where possible:

It’s just the profile endpoint that keeps triggering which I don’t have anywhere in my code. I looked at the link you gave but I don’t see a mention of using a proper endpoint vs an improper one…am I missing something? I also dont see a sample app to clone. The link in your docs HERE is broken

Hi again!

I am sorry about the late reply.

Regarding the sample application available on github, you can access it here.

Otherwise, I am still investigating the matter and come back with an update as soon as possible!

Kind Regards,
Nik

Hi!

We’re also seeing the /auth/profile endpoint being called every few seconds in our Next application running SDK v4.9.0. We tested with the official sample app as @nik.baleca suggested and observed the same behavior.

It sounds like this isn’t expected behavior, did you find out if there’s a way to configure/disable it @mmaccou?

Still no update here? In v3, /auth/me was being called once via useUser(). If the user was not authenticated, it returned a 204. In v4 /auth/profile is being called constantly and returning a 401 if user is not authenticated. Other than the vague notes about useUser behavior in the docs, I don’t see any info on this or how to configure it.

For those who end up here, it’s not documented in any of the guides, but there is a noContentProfileResponseWhenUnauthenticated configuration option that defaults to false. Setting it to true will go back to returning a 204.

Still would like input on the constant re-fetching of /auth/profile with useUser()

yea id also like some guidance on this. @nik.baleca can you jump in?

Hi everyone, sorry for the late update on this post!

As far as I have investigated regarding the matter, this might be expected behaviour due to the way the SDK is designed to work with the App and API routes.

Before going to possible solutions on the matter, to provide more information on the possible causes and on the matter in general.

  • The userUser() hook relies on the swr library in order to fetch user data from the routes defined and it is run whenever a component requests user data
  • The SDK typically requires you to create a dynamic or static API route in the route.ts. When a user is not logged in, the getSession function finds no session cookie and often returns a 401 Unauthorized status.
    *If the middleware determines the user is not authenticated, it will tipically redirect the user to the login page. However, a client-side data fetch (like SWR) cannot follow a 302/307 redirect since it expects a JSON response.

Moving on to the possible solution:

  • You can try to create the API route handler that the useUser hook is calling. This route will properly handle the unauthenticated state, turning the failed request into a clean 401 Unauthorized error. You would need to make the necessary changes in the route.ts or profile.ts files:
import { auth0 } from "@/lib/auth0";
import { NextResponse } from 'next/server';

export async function GET(request: NextRequest) {
  try {
    // checking for the Auth0 session cookie
    const session = await auth0.getSession(request);

    if (!session || !session.user) {
      //Return the 401 error if no session is detected
      return new NextResponse(JSON.stringify({ message: "Unauthorized" }), { 
        status: 401 
      });
    }

    // return user data if user is logged in
    return NextResponse.json(session.user);
  } catch (error) {
    // catch possible 
    return new NextResponse(JSON.stringify({ message: "Internal Server Error" }), {
      status: 500
    });
  }
}
  • Once your /auth/profile route correctly returns a 401 (not a redirect), you can adjust your middleware configuration to exclude the profile route from the general authentication check, letting the dedicated API route handle it:
export const config = {
  matcher: [
    "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt|auth/profile).*)",
  ],
}

Please let me know if the proposed solution works for your environments or if you still experience issues regarding the matter!

Looking forward to your replies!

Kind Regards,
Nik