Umbraco 13 Content Delivery protected content

I have follewed this documentation, Protected content in the Delivery API | Umbraco CMS the path to use to use external identity providers.

So the setup is
Azure Container app witch running NextJs
Azure web app with is running the delivery api.

So everything is working fine, but when the client (NextJs) navigate to /my-page and needs to login the some funky shit is happing. The I am using NextJs.Auth witch sends the challange to Umbraco, and Umbraco sends my to the external identity providers (MitId) and comes back to Umbraco and umbraco deliveres a accesstoken back to nextJs and now i can see /my-page.

Everythings works! Great! Then i push my code to the dev setup, same story everything works everybody happy, same as Test. But on production is an other story.
Nothing works.
Peopel navigate to /my-page go to MitID logs on and then unauthized.
I can see in the log the successfully logs in, the successfully obtiane a token furthe the endpoint /umbraco/delivery/api/v1/security/member/token and successfully get user data futhe this endpoint /umbraco/delivery/api/v1/security/member/userinfo
but when this endpoint is hit umbraco/delivery/api/v2/content/item/${path}?expand=all
and headers Authorization: `Bearer is set with the accesstoken i get an exception:

{"@t":"2025-04-09T10:42:57.6235119Z","@mt":"The event {EventName} was marked as rejected by {HandlerName}.","@l":"Debug","@tr":"34eba3efbb755d84b511ffbd6f4d1e8a","@sp":"1b9dec04e3d82297","EventName":"OpenIddict.Validation.OpenIddictValidationEvents+ProcessAuthenticationContext","HandlerName":"OpenIddict.Validation.OpenIddictValidationHandlers+ValidateRequiredTokens","SourceContext":"OpenIddict.Validation.OpenIddictValidationDispatcher","ActionId":"8be6088e-637b-4c3b-9c00-aa6c88548de9","ActionName":"Umbraco.Cms.Api.Delivery.Controllers.Content.QueryContentApiController.QueryV20 (Umbraco.Cms.Api.Delivery)","RequestId":"40004ae3-0001-f600-b63f-84710c7967bb","RequestPath":"/umbraco/delivery/api/v2/content","ProcessId":6804,"ProcessName":"w3wp","ThreadId":48,"ApplicationId":"ea6c9907b5dfb977abd279e5dd977d85f29f78cb","MachineName":"WN1SDWK00030C","Log4NetLevel":"DEBUG","HttpRequestId":"1b7992c5-cca4-4c32-a96a-10943506d97c","HttpRequestNumber":6433,"HttpSessionId":"3d126f9d-9646-d3d0-f378-f86818007e3e"}
{"@t":"2025-04-09T10:42:57.6235231Z","@mt":"AuthenticationScheme: {AuthenticationScheme} was not authenticated.","@l":"Debug","@tr":"34eba3efbb755d84b511ffbd6f4d1e8a","@sp":"1b9dec04e3d82297","AuthenticationScheme":"OpenIddict.Validation.AspNetCore","EventId":{"Id":9,"Name":"AuthenticationSchemeNotAuthenticated"},"SourceContext":"OpenIddict.Validation.AspNetCore.OpenIddictValidationAspNetCoreHandler","ActionId":"8be6088e-637b-4c3b-9c00-aa6c88548de9","ActionName":"Umbraco.Cms.Api.Delivery.Controllers.Content.QueryContentApiController.QueryV20 (Umbraco.Cms.Api.Delivery)","RequestId":"40004ae3-0001-f600-b63f-84710c7967bb","RequestPath":"/umbraco/delivery/api/v2/content","ProcessId":6804,"ProcessName":"w3wp","ThreadId":48,"ApplicationId":"ea6c9907b5dfb977abd279e5dd977d85f29f78cb","MachineName":"WN1SDWK00030C","Log4NetLevel":"DEBUG","HttpRequestId":"1b7992c5-cca4-4c32-a96a-10943506d97c","HttpRequestNumber":6433,"HttpSessionId":"3d126f9d-9646-d3d0-f378-f86818007e3e"}

i have dobbel, trippel check everything but can not see the error.
can somebody help me?

It’s a tough one, sounds like something is different on production. I am not very familiar with identity providers, but it’s good that everything is working on dev, that means you can focus on what is different between dev and live.
I assume there’s plenty of configuration changes between the two environments, it’s easy to miss one.

The error indicates that your Authorization: Bearer <your_token_here> header might have a problem:

  • Is it issued by the expected authority?
  • Is it valid (not expired)?
  • Does it include the required claims?

That is the funny thing. There is not much to see why it is going to unauthized.

Do i take the NextJs to Umbraco Delivery Api Authentication.
The only configuration parameter witch according to the documentation is the URL.
The client ID is hardcoded til be “Umbraco-member” and the is not client secret, and scopes is the same on all servers “openid”

Even the delivery Key is the same on all servere :wink:

The external login provider diffes off course, do to login with a real MitId or a test user.
But it is a client id and secret and it works.

The only differ the really is is that the Container app in production runs on a DNS, so not the azure pre deteminate hostname.

I have try to Teamviewer customers, and there is a bearer token and it is valid. I have also try to look on GitHub - kjac/UmbracoDeliveryApiAuthDemo: Client and server demonstrating member auth against the Umbraco Delivery API and we near do the same, i just you the external authentication.

It is sooooo stranges, also try to override the Umbraco configuration to disbaled diffent Tokenvalidator but with no sucess.

The only thing i can see is that the code there throws the error is this:

public ValueTask HandleAsync(ProcessAuthenticationContext context)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if ((context.RequireAccessToken       && string.IsNullOrEmpty(context.AccessToken))       ||
                (context.RequireAuthorizationCode && string.IsNullOrEmpty(context.AuthorizationCode)) ||
                (context.RequireDeviceCode        && string.IsNullOrEmpty(context.DeviceCode))        ||
                (context.RequireGenericToken      && string.IsNullOrEmpty(context.GenericToken))      ||
                (context.RequireIdentityToken     && string.IsNullOrEmpty(context.IdentityToken))     ||
                (context.RequireRefreshToken      && string.IsNullOrEmpty(context.RefreshToken))      ||
                (context.RequireUserCode          && string.IsNullOrEmpty(context.UserCode)))
            {
                context.Reject(
                    error: Errors.MissingToken,
                    description: SR.GetResourceString(SR.ID2000),
                    uri: SR.FormatID8000(SR.ID2000));

                return default;
            }

            return default;
        }