Your Next.js app is suddenly asking for credentials even though you haven’t explicitly configured authentication.

This usually means a component or route handler is trying to access user information or protected resources, but the authentication middleware hasn’t successfully established a user session. The system is correctly flagging that it doesn’t know who is making the request, so it’s defaulting to an unauthenticated state and prompting for login.

Here’s how to get Auth0 hooked up for server-side authentication in your Next.js app:

Common Causes and Fixes

  1. Auth0 SDK Not Initialized on the Server:

    • Diagnosis: Check your _app.js (or _app.tsx) file. Ensure Auth0Provider is wrapping your entire application. Crucially, verify that the backend configuration within Auth0Provider is correctly set up to initialize the Auth0 SDK on the server-side.
    • Fix: In _app.js:
      import { Auth0Provider } from '@auth0/nextjs-auth0';
      
      function MyApp({ Component, pageProps }) {
        return (
          <Auth0Provider
            domain="YOUR_AUTH0_DOMAIN"
            clientId="YOUR_AUTH0_CLIENT_ID"
            // This is crucial for server-side auth
      
            backend={{
      
              domain: "YOUR_AUTH0_DOMAIN", // Same as above
              clientId: "YOUR_AUTH0_CLIENT_ID", // Same as above
              clientSecret: "YOUR_AUTH0_CLIENT_SECRET", // Get this from Auth0 API settings
              audience: "YOUR_API_AUDIENCE", // Often your API identifier
              scope: "read:users", // Or whatever scopes your API needs
            }}
            redirectUri={`${process.env.NEXT_PUBLIC_APP_URL}/api/auth/callback`}
          >
            <Component {...pageProps} />
          </Auth0Provider>
        );
      }
      export default MyApp;
      
    • Why it works: The backend configuration tells the Auth0 SDK how to interact with your Auth0 tenant directly from your Next.js server. This allows it to validate tokens, fetch user profiles, and manage sessions without relying solely on client-side JavaScript.
  2. Missing or Incorrect Environment Variables:

    • Diagnosis: The Auth0 SDK relies on environment variables for its configuration. If these are missing or incorrect, the SDK won’t be able to connect to Auth0. Check your .env.local file.
    • Fix: Ensure you have these variables defined in your .env.local file:
      NEXT_PUBLIC_APP_URL=http://localhost:3000 # Or your deployed app URL
      AUTH0_SECRET=YOUR_VERY_LONG_RANDOM_SECRET_FOR_SESSION_ENCRYPTION
      AUTH0_BASE_URL=http://localhost:3000 # Or your deployed app URL
      AUTH0_ISSUER_BASE_URL=https://YOUR_AUTH0_DOMAIN
      AUTH0_CLIENT_ID=YOUR_AUTH0_CLIENT_ID
      AUTH0_CLIENT_SECRET=YOUR_AUTH0_CLIENT_SECRET
      AUTH0_AUDIENCE=YOUR_API_AUDIENCE
      
      Note: AUTH0_SECRET is for session encryption. Generate a long, random string for this.
    • Why it works: These variables provide the Auth0 SDK with the necessary credentials and URLs to communicate with your Auth0 tenant and your application’s callback endpoint securely.
  3. Callback URL Not Registered in Auth0:

    • Diagnosis: Auth0 needs to know which URLs it’s allowed to redirect users back to after authentication. If your Next.js callback URL isn’t registered, the redirect will fail.
    • Fix: In your Auth0 dashboard, go to "Applications" -> "Settings". Under "Allowed Callback URLs", add http://localhost:3000/api/auth/callback (or your deployed app’s equivalent).
    • Why it works: This explicitly authorizes your Next.js application to receive authentication responses from Auth0, completing the login flow.
  4. getSession Called Before Auth0Provider is Ready:

    • Diagnosis: If you’re calling getSession (from @auth0/nextjs-auth0) in a way that executes before the Auth0Provider has fully initialized, it will return null for the user. This often happens in page-level getServerSideProps or getStaticProps if not handled carefully.
    • Fix: Ensure getSession is only called within components or functions that are guaranteed to be descendants of Auth0Provider, or pass the req object correctly if calling it directly in getServerSideProps:
      import { withPageAuthRequired, getSession } from '@auth0/nextjs-auth0';
      
      export const getServerSideProps = withPageAuthRequired({
        async getServerSideProps(context) {
          const session = await getSession(context.req, context.res); // Pass req and res
          const user = session.user;
          // ... rest of your props
          return { props: { user } };
        }
      });
      
    • Why it works: getSession needs access to the request and response objects to correctly retrieve or create the session cookie managed by the Auth0 SDK.
  5. API Route Protection Misconfiguration:

    • Diagnosis: If you’re protecting API routes (e.g., /api/protected) using withApiAuthRequired, but the underlying session isn’t established, these routes will also reject requests.
    • Fix: In your API route file (e.g., pages/api/protected.js):
      import { withApiAuthRequired, getSession } from '@auth0/nextjs-auth0';
      
      export default withApiAuthRequired(async function protectedApi(req, res) {
        const session = await getSession(req, res); // Ensure session is retrieved
        res.json({ user: session.user });
      });
      
    • Why it works: withApiAuthRequired acts as a middleware. It internally calls getSession to verify the user’s session before allowing the request to proceed to your actual API handler logic.
  6. Incorrect audience or scope in Backend Configuration:

    • Diagnosis: If your server-side code needs to make authenticated calls to a separate API (e.g., your own backend API secured by Auth0), the audience and scope in the Auth0Provider’s backend configuration must match what your API expects.
    • Fix: In _app.js (as shown in point 1), ensure backend.audience and backend.scope are correctly set. For example, if your API identifier in Auth0 is https://my.api.com, use that for audience. If your API requires specific permissions, list them in scope.
    • Why it works: The audience identifies the API you’re trying to access, and the scope defines the permissions your application has been granted for that API. This information is used to construct the correct access token.

After applying these fixes, you should be able to log in via Auth0 and have your server-side code correctly identify the authenticated user.

The next error you’ll likely encounter is a CORS issue if your Next.js frontend tries to access an API that isn’t configured to allow requests from your frontend’s origin.

Want structured learning?

Take the full Auth0 course →