Share via

Custom Authentication Extension (EmailOtpSend) attachment breaks signup with no diagnostic logs in External ID

Robert Lalouche 5 Reputation points
2026-05-20T17:00:55.0633333+00:00

Environment

  • Identity service: Microsoft Entra External ID (CIAM)
  • Feature: Custom Authentication Extension, event type EmailOtpSend
  • Hosting: Extension endpoint runs on Azure App Service (NestJS/Node), publicly reachable, returns HTTP 401 to unauthenticated POSTs (proving the route is mapped and the bearer-token guard is active).

Problem

When I attach the EmailOtpSend extension to a user-facing app registration via the extension's Applications tab, signup fails immediately after the user enters their email and clicks Next. The end user sees the generic message:

"There was an issue looking up your account. Tap Next to try again."

Detaching the extension restores signup (with Microsoft's default *.onmicrosoft.com sender — the very deliverability problem the custom sender is meant to fix). Reattaching breaks signup again, reliably.

Most importantly — no diagnostic trail

I cannot find any failure record from Entra's side:

  • No failed entries in Monitor → Sign-in logs → Service principal sign-ins
  • No related entries in Monitor → Audit logs
  • No HTTP requests reach my extension endpoint during failed signup attempts (verified in App Service log stream and request logs)
  • Setting the extension's Error handling to "Show error" (instead of "Fallback to Microsoft default email OTP") produces the same generic user message — no specific error code surfaced

Behavior is identical on web (Next.js / MSAL.js) and mobile (React Native / native OAuth flow). Both use the same user-facing app registration.

What I've verified is configured

  1. Extension's backing app reg has Microsoft Graph CustomAuthenticationExtensions.Receive.Payload application permission granted, with admin consent.
  2. App role CustomAuthExt.Invoke (Application member type) created on the extension's app reg; granted to the user-facing app reg via API permissions → My APIs → Application permissions; admin consent granted.
  3. Microsoft's well-known custom-extensions caller client (99045fe1-7639-4a75-9d4a-577b6ca3810f) added as Authorized client application on the extension's exposed scope.
  4. The extension's backing app reg has its Application ID URI set to the required api://<endpoint-host>/<appId> format.
  5. The extension's API Authentication tab points at the correct app reg (verified via Overview → App ID GUID matches).
  6. Endpoint accepts POST and returns HTTP 401 + correct WWW-Authenticate when called without a bearer token (verified via curl).

What I tried

  • Initially the wizard auto-bound the extension to my user-facing app reg (audience reuse). I changed it via the Change button on API Authentication to point at a dedicated app reg. Same failure.
  • Permission granted via both the Expose an API → scope path and the App roles path. Same failure.
  • Added Microsoft's caller client as Authorized client. Same failure.
  • Tried "Show error" error handling. Same generic user message — no surfaced error.
  • Tested in incognito on multiple browsers (Safari, Chrome). Same failure.
  • Detach/reattach cycles consistently flip the behavior (detach → works; attach → breaks).

My ask

Microsoft engineers — please check your backend logs for invocation attempts from my tenant to this extension target URL during a failed signup. Why is Entra refusing to invoke the extension, and which permission / configuration item is still missing? The lack of any failure entry in Sign-in / Audit logs is making this impossible to self-diagnose.

I'm happy to provide my tenant ID, app reg IDs, and a timestamp of a reproducer over a private channel.

Microsoft Security | Microsoft Entra | Microsoft Entra External ID

1 answer

Sort by: Most helpful
  1. AI answer

    2026-05-20T17:01:45.68+00:00

    The behavior matches Entra refusing to invoke the custom authentication extension because of a configuration/validation error that occurs before the REST call is made. In such cases, Entra returns only a generic error to the user and doesn’t mint a token or call the extension, and the detailed error is only visible in the sign-in logs for the app.

    From the documented error model for custom authentication extensions:

    • When an API call fails or the extension configuration is invalid, Entra does not mint a token and returns a generic error to the client for OpenID Connect apps.
    • The error code that explains why the extension wasn’t invoked is surfaced only in Microsoft Entra sign-in logs under the Authentication Events tab for the affected sign-in.
    • The error codes include both “pre-call” configuration/permission issues and “call-time” issues. Many of these prevent Entra from calling the REST endpoint at all.

    Given that no HTTP request reaches the endpoint, the issue is almost certainly in this “pre-call” category. The relevant documented error codes and what to check are:

    1. Domain / Application ID URI alignment
      • Error code 1003015CustomExtensionDomainNameDoesNotMatch: “The targetUrl and resourceId of the custom extension should have the same fully qualified domain name.”
      • Error code 1003014CustomExtensionIncorrectResourceIdFormat: “The identifierUris property in the manifest for the application registration for the custom extension, should be in the format of "api://{fully qualified domain name}/{appid}.”
      Even if the Application ID URI is set, Entra validates that:
      • resourceId (Application ID URI / identifierUris) uses the exact api://<fully qualified domain name>/<appId> format, and
      • The targetUrl host matches that fully qualified domain name.
    2. Service principal existence and state
      • Error code 1003016CustomExtensionResourceServicePrincipalNotFound: “The appId of the custom extension resourceId should correspond to a real service principal in the tenant.”
      • Error code 1003017CustomExtensionClientServicePrincipalNotFound.
      • Error code 1003018CustomExtensionClientServiceDisabled.
      • Error code 1003019CustomExtensionResourceServicePrincipalDisabled.
      If the backing or client service principal is missing or disabled, Entra will not call the extension and will surface only a generic error to the user.
    3. Permission / consent issues
      • Error code 1003021CustomExtensionPermissionNotGrantedToServicePrincipal: “The service principal doesn't have admin consent for the Microsoft Graph CustomAuthenticationExtensions.Receive.Payload app role (application permission) which is required for the app to receive custom authentication extension HTTP requests.”
      • Error code 1003022CustomExtensionMsGraphServicePrincipalDisabledOrNotFound.
      Even if consent appears granted, Entra validates that the service principal actually has the CustomAuthenticationExtensions.Receive.Payload app role and that the Microsoft Graph service principal is present and enabled.
    4. Endpoint / URL validation
      • Error code 1003020CustomExtensionIncorrectTargetUrlFormat: “The target URL is in an improper format. It must be a valid URL that starts with https.”
      • Error code 1003023CustomExtensionBlocked: “The endpoint used for the custom extension is blocked by the service.”
    5. Other configuration errors
      • Error code 1003011CustomExtensionNotFound: “The custom extension associated with an event listener couldn't be found.”
      • Error code 1003000EventHandlerUnexpectedError.
      • Error code 1003001CustomExtensionUnexpectedError.

    In all of these cases, Entra can fail the sign-up/sign-in flow before any REST call is made, which matches the observation that the endpoint never sees traffic.

    To get the actual reason in this scenario, the documented path is:

    1. Go to the Microsoft Entra admin center.
    2. Navigate to Entra ID → Enterprise apps → Sign-in logs.
    3. Select the latest sign-in log for the affected app.
    4. Open the Authentication Events tab.
    5. Inspect the event corresponding to the custom authentication extension; the error code and details for the extension invocation (or pre-call validation failure) are shown there.

    That error code can then be mapped directly using the documented error code reference to identify whether the issue is:

    • Domain mismatch (1003015),
    • Incorrect Application ID URI format (1003014),
    • Missing/disabled service principal (10030161003019),
    • Missing CustomAuthenticationExtensions.Receive.Payload permission (1003021),
    • Target URL format or blocking (1003020, 1003023), or
    • Another configuration error (10030001003003, etc.).

    Once the configuration issue indicated by that code is corrected, Entra will begin calling the REST endpoint. If the endpoint then fails at runtime (timeout, invalid response, etc.), the same sign-in logs and error code reference (for example 1003002, 1003003, 1003005, 1003006, 1003009, 1003010, 1003007, 1003008, 1003024, 1003025, 1003026, 1003027) can be used to diagnose those issues.


    References:

    AI-generated content may be incorrect. Read our transparency notes for more information.

    Was this answer helpful?

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.