Authenticate to a backend API from NextJS using the SDK

I’ll start with my architecture:

Frontend: NextJS (Using the beta SDK)
Backend: ASP NET WebAPI
Auth: Auth0, using the SDK throughout the whole stack.

I have authentication setup on the frontend, and I have my backend setup to check the JWT token for the proper audience.

builder.Services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
    {
        options.Authority = builder.Configuration["Auth0:Domain"];
        options.Audience = builder.Configuration["Auth0:Audience"];
        options.TokenValidationParameters = new TokenValidationParameters
        {
            NameClaimType = ClaimTypes.NameIdentifier
        };
    });

The issue that I’m having is that with the JWT provided when logging in with the NextJS SDK does not seem to provide a way to pass an audience when calling getAccessToken, so I end up not being able to call my backend api with the token generated on the frontend.

How would I go about getting an access token with the proper audience, so that I can use the same token to:

  • Be authenticated on the frontend
  • Use the same token to authenticate to the backend

OR am I going about this in the wrong way entirely? This is my first foray into building OAuth into a frontend application, so I may be doing some things incorrectly.

The NextJS SDK is likely giving you an ID token by default, which is meant for frontend authentication, while your backend expects an access token with a specific audience.

  1. First, in your NextJS frontend, you need to configure the Auth0 SDK with both the audience and scope when initializing:
// auth0-config.ts or similar
import { Auth0Provider } from '@auth0/auth0-react';

const Auth0ProviderWithConfig = ({ children }) => {
  return (
    <Auth0Provider
      domain={process.env.NEXT_PUBLIC_AUTH0_DOMAIN}
      clientId={process.env.NEXT_PUBLIC_AUTH0_CLIENT_ID}
      authorizationParams={{
        redirect_uri: window.location.origin,
        audience: 'YOUR_API_IDENTIFIER', // This should match your backend Audience
        scope: 'openid profile email' // Add any additional scopes you need
      }}
    >
      {children}
    </Auth0Provider>
  );
};
  1. Then, when you need to make API calls, use getAccessTokenSilently() instead of getAccessToken():
import { useAuth0 } from '@auth0/auth0-react';

const MyComponent = () => {
  const { getAccessTokenSilently } = useAuth0();

  const callApi = async () => {
    try {
      const token = await getAccessTokenSilently();
      
      // Use this token in your API calls
      const response = await fetch('your-api-endpoint', {
        headers: {
          Authorization: `Bearer ${token}`
        }
      });
    } catch (error) {
      console.error(error);
    }
  };
};
  1. Your backend configuration looks correct, but make sure the Audience value matches exactly what you configured in Auth0 and what you’re passing in the frontend configuration.

  2. In Auth0’s dashboard, make sure you:

  • Have created an API with the identifier matching your audience
  • Have authorized your application to request access tokens for this API
  • Have the correct allowed callback URLs set up