Next.js App Router (Auth0Client): getAccessToken returns encrypted JWE (alg: dir) instead of JWT (RS256) despite correct Audience

Hi everyone,

I am facing a persistent issue integrating a Next.js 15+ (App Router) frontend with a Python (FastAPI) backend.

The Problem: Even though I have configured the audience correctly in my Auth0Client instantiation, the auth0.getAccessToken() method in my Next.js API route returns an encrypted token (alg: dir, JWE) instead of the expected signed JWT (alg: RS256).

My Python backend rejects this token because it expects a standard RS256 Access Token to validate against the JWKS.

My Stack:

  • SDK: @auth0/nextjs-auth0 (Latest version using App Router setup)

  • Frontend: Next.js 15 (App Router)

  • Backend: Python / FastAPI

  • Flow: Authorization Code Flow

Configuration:

  1. Dashboard Settings:

    • API Identifier: https://vision-api

    • Signing Algorithm: RS256

    • JSON Web Encryption (JWE): Disabled (I double-checked this).

    • Application (M2M) is authorized for this API.

  2. Next.js Implementation (src/lib/auth0.ts): I am instantiating the client manually to use in the App Router:

    TypeScript

    import { Auth0Client } from "@auth0/nextjs-auth0/server";
    
    export const auth0 = new Auth0Client({
      // domain, clientID, secret are loaded from env
      authorizationParams: {
        scope: 'openid profile email offline_access',
        audience: 'https://vision-api', // <--- Explicitly set here
      },
    });
    
    
  3. The Proxy Route (src/app/api/proxy/route.ts):

    TypeScript

    import { auth0 } from '@/lib/auth0';
    
    export async function GET(req: NextRequest) {
      try {
        const tokenResponse = await auth0.getAccessToken();
        const accessToken = tokenResponse.accessToken || tokenResponse.token;
    
        // DEBUG LOGGING
        console.log("Token Header:", decodeHeader(accessToken)); 
        // OUTPUT: { "alg": "dir", "enc": "A256GCM", ... } -> THIS IS THE ISSUE
      } catch (error) {
        // ...
      }
    }
    
    
  4. The Auth Route (src/app/api/auth/[auth0]/route.ts):

    TypeScript

    import { auth0 } from '@/lib/auth0';
    export const GET = auth0.handleAuth();
    
    

What I have verified (Debugging):

  1. Manual CURL Test (Success): If I request a token manually using client_credentials via terminal:

    Bash

    curl --request POST --url ... --data '{"audience":"https://vision-api", ...}'
    
    

    I receive a correct RS256 JWT. I can pass this token to my Python backend and it works perfectly (HTTP 200). This proves the API and Auth0 Dashboard configuration are correct.

  2. Browser Network Tab: When checking the /authorize request initiated by the Next.js app, I suspect the audience parameter might not be passing through correctly, causing Auth0 to issue an opaque/encrypted session token instead of an API Access Token.

The Question: Why does @auth0/nextjs-auth0 return an opaque/encrypted JWE (alg: dir) even when:

  1. audience is set in authorizationParams.

  2. JWE is disabled in the API settings in the Dashboard.

  3. I am requesting a token for a Custom API.

How can I force the SDK to retrieve the decrypted RS256 Access Token so I can pass it to my external backend?

Any help is appreciated.