Entra External ID CIAM extensions not binding to proven Functions Endpoint

Richard Collins 21 Reputation points
2026-03-16T15:44:05.2166667+00:00

Issue summary

After 21 hours of trials and attempts we cannot see what is left to try.

Simply sign up works end to end. When the simplest of functions is added, which just opens and returns and logs okay, it returns and the signup aborts with message.

We are unable to complete a CIAM custom authentication extension (Before/After) for a working Azure Functions HTTP endpoint. Despite the Function executing and returning a valid CIAM‑compliant response, the CIAM user flow fails immediately after the callback with:

AADSTS1100001: Non-retryable error has occurred.
Underlying error code: 1003009

Based on repeated, clean-room repros and screenshots, the CIAM extension wizard in our tenant intermittently fails to expose or honor the “Resource application” selector and/or binds the extension to the wrong application (client app) instead of our Resource API application, causing audience mismatch and the consistent 1003009 failure.


Environment

  • Tenant (External ID / CIAM): IRSLOBBY – Tenant ID 8299aefb-503c-48f5-bc8c-293d6acdf888
  • User flow: PPXMFlow
  • Function App (Windows classic Consumption / Y1): ciamprovingy1 (Node ~24)
  • Function (v3 model): CIAMproof at route POST /api/ciam/proof
  • Function returns CIAM‑compliant schema: {"version":"1.0.0","action":"Continue","userAttributes":[],"userDefinedClaims":[{"claimId":"echoEventType","value":"..."}]}
  • API (Resource) application intended for binding: CIAMprovingAPIclean
    • App ID: 8cd9257d-a7b6-4a76-aa7c-80e1560ee36f
      • Application ID URI: api://ciamprovingy1.azurewebsites.net/8cd9257d-a7b6-4a76-aa7c-80e1560ee36f
        • (Has a Service Principal; signInAudience set to multi‑tenant + MSA; exposes a simple “access” scope or, under new CIAM model, uses the built‑in “Receive custom authentication extension HTTP requests” binding.)

What works (proven)

  • The Function endpoint is reachable and executes successfully from CIAM:
    • Logs (multiple times) show:
       - `Request successfully matched the route 'api/ciam/proof'`
      
             - `AuthenticationScheme: WebJobsAuthLevel was successfully authenticated.`
      
                   - `Executing 'Functions.CIAMproof' …`
      
                         - **`[CIAMProof] event=microsoft.graph.authenticationEvent.attributeCollectionStart`**
      
                               - `Executed 'Functions.CIAMproof' (Succeeded, Duration≈7–25ms)`
      
                               - Manual `curl` POST to the function with a valid function/host key returns HTTP 200 and the expected CIAM JSON.
      
                               - Function discovery is now stable (v3 structure: `/wwwroot/host.json` + `/wwwroot/CIAMproof/function.json,index.js`).
      

Conclusion: The Function App is not the problem. The failure happens after we return 200—inside CIAM’s validation.


What fails (symptoms)

Immediately after the Function returns 200 OK, CIAM fails the step with AADSTS1100001 / 1003009. Representative instances (UTC):

  • 2026‑03‑15 20:14:05Z — Request Id a17d9cb4-1854-43a1-9c36-917a095b0100, Correlation Id 5d0d918b-2006-4fd7-b0a6-ad896cff9f94
  • 2026‑03‑15 22:21:56Z — Request Id 9477a325-06ba-4c7d-a2b2-f5f8527f0100, Correlation Id 82db1baa-9e80-4afc-b441-8af3516bb092
  • 2026‑03‑15 22:29:24Z — Request Id ab7b01bb-6aef-4a30-832a-da4957f90000, Correlation Id 2841489d-9419-424f-ab04-00dc4ed5dd31
  • 2026‑03‑16 00:31:28Z — Request Id 8cf4b6b5-85fd-4a50-8152-382ae7a40100, Correlation Id 09256dcb-1e6c-44cb-8e15-db1d50823e6c
  • 2026‑03‑16 14:02:38Z — Request Id 093b5827-8467-42dc-820e-32b4b5530300, Correlation Id 2155dfef-a5c5-4939-8357-ad86899e7ed8

Observation: These errors occur only when the extension is attached; user flow without the extension completes and creates the user successfully.


Attempts already made (chronology & highlights)

Function side

  • Migrated off Flex Consumption (v4 model) to Windows classic Y1; rebuilt as Node v3 with function.json + index.js.
    • Verified portal “Code + Test” and Application Insights show successful invocations with expected event types.
      • Confirmed Function keys/host keys and correct URL with ?code=.
      API app (Resource)
      - Created **`CIAMprovingAPIclean`** as a clean API app.
      
         - Set **Application ID URI** to the Function hostname + appId.
      
            - Ensured Service Principal exists; signInAudience is multi‑tenant/MSA.
      
               - In newer CIAM UI, “Required permission: Receive custom authentication extension HTTP requests” is displayed (no legacy scope picker).
      
               **Service principal visibility & audience**
      
                  - Ensured the **Resource application** SP appears in Enterprise applications (verified).
      
                     - Confirmed visible `servicePrincipalNames` include both the GUID and the Application ID URI.
      
                     **Extension creation – multiple rounds (Edge/Chrome/Firefox)**
      
                        - Created **Before** extensions via “Create new app registration” **and** via “Select an existing app registration”.
      
                           - Reproduced on fresh browser sessions (incl. Firefox just installed), new tabs, and with >5–8s hydration waits on each wizard panel.
      
                              - **Consistent anomaly**: The **API Authentication** panel often **omits** the **“Resource application: Change”** block entirely; when it appears, selecting `CIAMprovingAPIclean` does not always persist back to the summary, which then shows:
      
                                    - **Resource application = a newly generated client app** (e.g., `Extra001`, `CIAMautobuild2`, `CIAMprovingy1Before`)
      
                                          - **Required app ID URI = `api://…/{appid}`** (placeholder) or the client app ID—**not** the API app ID
      
                                                - **Required permission = “Configured”** (placeholder) instead of the fully‑resolved string
      
                                                   - Attaching such an extension to the flow yields 1003009 every time, even though the Function ran successfully.
      
                                                   **Clean slate & rebinding attempts**
      
                                                      - Deleted and re‑created extensions many times; waited between panels; changed names to force re‑hydration; tried both **Create new app registration** and **Select an existing app registration**.
      
                                                         - Confirmed the flow works **without** extensions (user creation & Power Pages sign‑in OK).
      

Conclusion from attempts: The wizard in our CIAM tenant intermittently fails to render or persist the Resource application selection and ends up binding the extension to its auto‑created client app rather than our API app—producing an audience mismatch and 1003009 immediately after the Function returns 200.


Expected vs Actual

Expected (working tenant):

  • API Authentication shows Resource application: CIAMprovingAPIclean (selectable)
    • Summary shows:
      - `Required app ID URI = api://ciamprovingy1.azurewebsites.net/8cd9257d-…-e36f`
      
            - `Required permission = Receive custom authentication extension HTTP requests`
      
               - User flow proceeds to Attribute Collection after the callback (no 1003009)
      
               **Actual (our tenant):**
      
                  - Resource application selector **often missing** or selection **not persisted**
      
                     - Summary shows **auto‑created client app** (e.g., *Extra001*) as Resource application and/or **`{appid}`** placeholder
      
                        - “Required permission” frequently shows **Configured**
      
                           - User flow fails with **AADSTS1100001 / 1003009** immediately after Function returns
      

Hypothesis

This looks like a CIAM tenant‑side wizard regression/caching defect where the Resource application binding is not surfaced or not applied. The extension is then saved without a correct Resource application audience, or with the client app set as the Resource—leading to token audience mismatch and 1003009.


What we need Microsoft to do

  1. Confirm the extension objects created in our tenant (latest failing one is fine) and verify which Resource application they are actually bound to.
    • Validate that the extension’s resourceApplicationId is 8cd9257d-a7b6-4a76-aa7c-80e1560ee36f (our API app).
      • If the binding points to an auto‑created client app (e.g., Extra001), please correct it and confirm the fix.
      1. Investigate why the “Resource application” selector is intermittently not rendered/persisted in the API Authentication panel for our tenant; we have provided multiple screenshots where the control is missing and/or the {appid} placeholder is shown on save.
      2. Provide a supported workaround for creating the extension via Microsoft Graph that explicitly sets resourceApplicationId = 8cd9…e36f (we’re willing to use Graph if that’s the current recommended path for affected tenants).
      3. Confirm whether, under the new CIAM model, the only permission expected is the built‑in “Receive custom authentication extension HTTP requests”, and that no legacy scope selection is required (our UI no longer shows scope pickers).

Repro steps (minimal)

  1. Function App ciamprovingy1 (Windows Y1, Node v3) with HTTP trigger CIAMproof at POST /api/ciam/proof—returns CIAM‑compliant JSON.
  2. Create custom extension (Before) → Wizard → API Authentication.
  3. Observed: Resource application selector often missing; when present, selecting CIAMprovingAPIclean does not persist back to summary (summary shows client app / {appid} placeholder).
  4. Attach extension to PPXMFlow and run sign‑up → Function executes 200 OKCIAM fails with AADSTS1100001 / 1003009.

Attachments available

  • Screenshots:
    • API Authentication without Resource application selector
      • Selection dialog listing CIAMprovingAPIclean among Enterprise applications
        • Summary pages showing Resource application = Extra001 (client app) and {appid} placeholders
          • Function logs showing successful invocation and event type
          • Request Ids / Correlation Ids (see list above)

Current status

  • Function endpoint is live and correct.
  • User flow without extensions completes as expected.
  • User flow with extension fails after the callback with 1003009 due to incorrect Resource application binding in the extension.
  • We need Microsoft to review/repair the extension objects in our tenant or provide a Graph‑based creation path that binds resourceApplicationId to 8cd9257d-a7b6-4a76-aa7c-80e1560ee36f explicitly.

If you want, I can also include a short Graph payload you can paste into az rest or Graph Explorer that creates the extension with the correct resourceApplicationId so Support can reproduce and compare.Below is a ready‑to‑paste statement you can use in your Microsoft support ticket.

I’ve captured environment details, exact steps tried, timestamps, app IDs/names, observed errors, and the working hypothesis that your CIAM extension wizard is not consistently binding to the correct Resource application—resulting in AADSTS1100001 / 1003009 even though the Function executes successfully.


Issue summary

We are unable to complete a CIAM custom authentication extension (Before/After) for a working Azure Functions HTTP endpoint.
Despite the Function executing and returning a valid CIAM‑compliant response, the CIAM user flow fails immediately after the callback with:

AADSTS1100001: Non-retryable error has occurred.
Underlying error code: 1003009

Based on repeated, clean-room repros and screenshots, the CIAM extension wizard in our tenant intermittently fails to expose or honor the “Resource application” selector and/or binds the extension to the wrong application (client app) instead of our Resource API application, causing audience mismatch and the consistent 1003009 failure.


Environment

  • Tenant (External ID / CIAM): IRSLOBBY – Tenant ID 8299aefb-503c-48f5-bc8c-293d6acdf888
  • User flow: PPXMFlow
  • Function App (Windows classic Consumption / Y1): ciamprovingy1 (Node ~24)
  • Function (v3 model): CIAMproof at route POST /api/ciam/proof
  • Function returns CIAM‑compliant schema:
    {"version":"1.0.0","action":"Continue","userAttributes":[],"userDefinedClaims":[{"claimId":"echoEventType","value":"..."}]}
  • API (Resource) application intended for binding:
    CIAMprovingAPIclean
    • App ID: 8cd9257d-a7b6-4a76-aa7c-80e1560ee36f
      • Application ID URI: api://ciamprovingy1.azurewebsites.net/8cd9257d-a7b6-4a76-aa7c-80e1560ee36f
        • (Has a Service Principal; signInAudience set to multi‑tenant + MSA; exposes a simple “access” scope or, under new CIAM model, uses the built‑in “Receive custom authentication extension HTTP requests” binding.)

What works (proven)

  • The Function endpoint is reachable and executes successfully from CIAM:
    • Logs (multiple times) show:
       - `Request successfully matched the route 'api/ciam/proof'`
      
             - `AuthenticationScheme: WebJobsAuthLevel was successfully authenticated.`
      
                   - `Executing 'Functions.CIAMproof' …`
      
                         - **`[CIAMProof] event=microsoft.graph.authenticationEvent.attributeCollectionStart`**
      
                               - `Executed 'Functions.CIAMproof' (Succeeded, Duration≈7–25ms)`
      
                               - Manual `curl` POST to the function with a valid function/host key returns HTTP 200 and the expected CIAM JSON.
      
                               - Function discovery is now stable (v3 structure: `/wwwroot/host.json` + `/wwwroot/CIAMproof/function.json,index.js`).
      

Conclusion: The Function App is not the problem. The failure happens after we return 200—inside CIAM’s validation.


What fails (symptoms)

Immediately after the Function returns 200 OK, CIAM fails the step with AADSTS1100001 / 1003009.
Representative instances (UTC):

  • 2026‑03‑15 20:14:05Z — Request Id a17d9cb4-1854-43a1-9c36-917a095b0100, Correlation Id 5d0d918b-2006-4fd7-b0a6-ad896cff9f94
  • 2026‑03‑15 22:21:56Z — Request Id 9477a325-06ba-4c7d-a2b2-f5f8527f0100, Correlation Id 82db1baa-9e80-4afc-b441-8af3516bb092
  • 2026‑03‑15 22:29:24Z — Request Id ab7b01bb-6aef-4a30-832a-da4957f90000, Correlation Id 2841489d-9419-424f-ab04-00dc4ed5dd31
  • 2026‑03‑16 00:31:28Z — Request Id 8cf4b6b5-85fd-4a50-8152-382ae7a40100, Correlation Id 09256dcb-1e6c-44cb-8e15-db1d50823e6c
  • 2026‑03‑16 14:02:38Z — Request Id 093b5827-8467-42dc-820e-32b4b5530300, Correlation Id 2155dfef-a5c5-4939-8357-ad86899e7ed8

Observation: These errors occur only when the extension is attached; user flow without the extension completes and creates the user successfully.


Attempts already made (chronology & highlights)

Function side

  • Migrated off Flex Consumption (v4 model) to Windows classic Y1; rebuilt as Node v3 with function.json + index.js.
    • Verified portal “Code + Test” and Application Insights show successful invocations with expected event types.
      • Confirmed Function keys/host keys and correct URL with ?code=.
      API app (Resource)
      - Created **`CIAMprovingAPIclean`** as a clean API app.
      
         - Set **Application ID URI** to the Function hostname + appId.
      
            - Ensured Service Principal exists; signInAudience is multi‑tenant/MSA.
      
               - In newer CIAM UI, “Required permission: Receive custom authentication extension HTTP requests” is displayed (no legacy scope picker).
      
               **Service principal visibility & audience**
      
                  - Ensured the **Resource application** SP appears in Enterprise applications (verified).
      
                     - Confirmed visible `servicePrincipalNames` include both the GUID and the Application ID URI.
      
                     **Extension creation – multiple rounds (Edge/Chrome/Firefox)**
      
                        - Created **Before** extensions via “Create new app registration” **and** via “Select an existing app registration”.
      
                           - Reproduced on fresh browser sessions (incl. Firefox just installed), new tabs, and with >5–8s hydration waits on each wizard panel.
      
                              - **Consistent anomaly**: The **API Authentication** panel often **omits** the **“Resource application: Change”** block entirely; when it appears, selecting `CIAMprovingAPIclean` does not always persist back to the summary, which then shows:
      
                                    - **Resource application = a newly generated client app** (e.g., `Extra001`, `CIAMautobuild2`, `CIAMprovingy1Before`)
      
                                          - **Required app ID URI = `api://…/{appid}`** (placeholder) or the client app ID—**not** the API app ID
      
                                                - **Required permission = “Configured”** (placeholder) instead of the fully‑resolved string
      
                                                   - Attaching such an extension to the flow yields 1003009 every time, even though the Function ran successfully.
      
                                                   **Clean slate & rebinding attempts**
      
                                                      - Deleted and re‑created extensions many times; waited between panels; changed names to force re‑hydration; tried both **Create new app registration** and **Select an existing app registration**.
      
                                                         - Confirmed the flow works **without** extensions (user creation & Power Pages sign‑in OK).
      

Conclusion from attempts: The wizard in our CIAM tenant intermittently fails to render or persist the Resource application selection and ends up binding the extension to its auto‑created client app rather than our API app—producing an audience mismatch and 1003009 immediately after the Function returns 200.


Expected vs Actual

Expected (working tenant):

  • API Authentication shows Resource application: CIAMprovingAPIclean (selectable)
    • Summary shows:
      - `Required app ID URI = api://ciamprovingy1.azurewebsites.net/8cd9257d-…-e36f`
      
            - `Required permission = Receive custom authentication extension HTTP requests`
      
               - User flow proceeds to Attribute Collection after the callback (no 1003009)
      
               **Actual (our tenant):**
      
                  - Resource application selector **often missing** or selection **not persisted**
      
                     - Summary shows **auto‑created client app** (e.g., *Extra001*) as Resource application and/or **`{appid}`** placeholder
      
                        - “Required permission” frequently shows **Configured**
      
                           - User flow fails with **AADSTS1100001 / 1003009** immediately after Function returns
      

Hypothesis

This looks like a CIAM tenant‑side wizard regression/caching defect where the Resource application binding is not surfaced or not applied. The extension is then saved without a correct Resource application audience, or with the client app set as the Resource—leading to token audience mismatch and 1003009.


What we need Microsoft to do

  1. Confirm the extension objects created in our tenant (latest failing one is fine) and verify which Resource application they are actually bound to.
    • Validate that the extension’s resourceApplicationId is 8cd9257d-a7b6-4a76-aa7c-80e1560ee36f (our API app).
      • If the binding points to an auto‑created client app (e.g., Extra001), please correct it and confirm the fix.
      1. Investigate why the “Resource application” selector is intermittently not rendered/persisted in the API Authentication panel for our tenant; we have provided multiple screenshots where the control is missing and/or the {appid} placeholder is shown on save.
      2. Provide a supported workaround for creating the extension via Microsoft Graph that explicitly sets resourceApplicationId = 8cd9…e36f (we’re willing to use Graph if that’s the current recommended path for affected tenants).
      3. Confirm whether, under the new CIAM model, the only permission expected is the built‑in “Receive custom authentication extension HTTP requests”, and that no legacy scope selection is required (our UI no longer shows scope pickers).

Repro steps (minimal)

  1. Function App ciamprovingy1 (Windows Y1, Node v3) with HTTP trigger CIAMproof at POST /api/ciam/proof—returns CIAM‑compliant JSON.
  2. Create custom extension (Before) → Wizard → API Authentication.
  3. Observed: Resource application selector often missing; when present, selecting CIAMprovingAPIclean does not persist back to summary (summary shows client app / {appid} placeholder).
  4. Attach extension to PPXMFlow and run sign‑up → Function executes 200 OKCIAM fails with AADSTS1100001 / 1003009.

Attachments available

  • Screenshots:
    • API Authentication without Resource application selector
      • Selection dialog listing CIAMprovingAPIclean among Enterprise applications
        • Summary pages showing Resource application = Extra001 (client app) and {appid} placeholders
          • Function logs showing successful invocation and event type
          • Request Ids / Correlation Ids (see list above)

Current status

  • Function endpoint is live and correct.
  • User flow without extensions completes as expected.
  • User flow with extension fails after the callback with 1003009 due to incorrect Resource application binding in the extension.
  • We need Microsoft to review/repair the extension objects in our tenant or provide a Graph‑based creation path that binds resourceApplicationId to 8cd9257d-a7b6-4a76-aa7c-80e1560ee36f explicitly.

Microsoft Security | Microsoft Identity Manager

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.