microsoft / microsoft/BCApps

[Bug]: API Webhook notification are never sent when user do not have direct read access against table to be notified

Open
#8,549 11 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Approved Team: Integrations
Dominant language
AL
Stars
683
Forks
459
Avg merge
3d 26m
Merged PRs (30d)
633

Description

Describe the issue

When a third party application is subscribed against a table to be notified about its changes using Webhook mechanism
If an user is writing inside subscribed table but don't have direct Read access on it
The notification job is queued and processing, but failing when reaching method IsNullUpdate while executing instruction if not RecordRef.GetBySystemId(APIWebhookNotification."Entity ID") then begin

This is producing the following trace :

"API Webhook Notification Send"(CodeUnit 6154).IsNullUpdate line 17 - Base Application by Microsoft
"API Webhook Notification Send"(CodeUnit 6154).GenerateAggregateNotifications line 15 - Base Application by Microsoft
"API Webhook Notification Send"(CodeUnit 6154).ProcessNotifications line 8 - Base Application by Microsoft
"API Webhook Notification Send"(CodeUnit 6154).OnRun(Trigger) line 39 - Base Application by Microsoft
"Job Queue Start Codeunit"(CodeUnit 449).OnRun(Trigger) line 18 - Base Application by Microsoft
"Job Queue Dispatcher"(CodeUnit 448).HandleRequest line 24 - Base Application by Microsoft
"Job Queue Dispatcher"(CodeUnit 448).OnRun(Trigger) line 22 - Base Application by Microsoft

Since it's an ACL related exception, the job is crashed and never requeued preventing changes to be sent against third party application.

Expected behavior

Ideally, subscribed third party application beeing notified anyway - user having or not direct read access against the subscribed table.

At worse, preventing the notification job to crash when user do not have read access on some tables related to existing subscriptions - allowing other events to be properly processed.

Steps to reproduce
  1. Assigning indirect read permission on table G/L Entry (17) to an User
  2. Granting user capability to queue job
  3. Granting user capability to process webhook notifications
  4. Subscribing against {businesscentralPrefix}/companies({id})/generalLedgerEntries endpoint Creating Webhook Subscription
  5. Using that user to post some Sales Invoice, producing G/L Entry and related Notification events
  6. Confirming processing notification AL00006ZT appears (Microsoft Telemetry), confirming webhook job is processing registered event

Workflow can be trigger using the following code snippet

            action(Test)
            {
                Caption = 'Test';

                trigger OnAction()
                var
                    APIWebhookSubscription: Record "API Webhook Subscription";
                    APIWebhookNotification: Record "API Webhook Notification";
                    OutStream: OutStream;
                begin
                    // mock webhook subscription
                    APIWebhookSubscription.SetRange("Source Table Id", Database::"G/L Entry");
                    if not (APIWebhookSubscription.FindLast()) then begin
                        APIWebhookSubscription.Init();
                        APIWebhookSubscription."Subscription Id" := CreateGuid();
                        APIWebhookSubscription."Entity Publisher" := '';
                        APIWebhookSubscription."Entity Group" := '';
                        APIWebhookSubscription."Entity Version" := 'v2.0';
                        APIWebhookSubscription."Entity Set Name" := 'generalLedgerEntries';
                        APIWebhookSubscription."Company Name" := CompanyName();
                        APIWebhookSubscription."User Id" := UserSecurityId();
                        APIWebhookSubscription."Last Modified Date Time" := CurrentDateTime();
                        APIWebhookSubscription."Client State" := 'dummystate';
                        APIWebhookSubscription."Expiration Date Time" := CurrentDateTime() + (1000 * 60 * 60 * 24);
                        APIWebhookSubscription."Subscription Type" := APIWebhookSubscription."Subscription Type"::Regular;
                        APIWebhookSubscription."Source Table Id" := Database::"G/L Entry";
                        APIWebhookSubscription.Insert();
                    end;

                    APIWebhookSubscription."Notification Url Prefix" := 'https://localhost/callback';
                    APIWebhookSubscription."Notification Url Blob".CreateOutStream(OutStream);
                    OutStream.WriteText(APIWebhookSubscription."Notification Url Prefix");

                    APIWebhookSubscription."Resource Url Blob".CreateOutStream(OutStream);
                    OutStream.WriteText(GetUrl(ClientType::Api, CompanyName, ObjectType::Page, Page::"APIV2 - G/L Entries"));
                    APIWebhookSubscription.Modify();

                    // mock pending notification
                    APIWebhookNotification.Init();
                    APIWebhookNotification.ID := CreateGuid();
                    APIWebhookNotification."Subscription ID" := APIWebhookSubscription."Subscription ID";
                    APIWebhookNotification."Created By User SID" := UserSecurityId();
                    APIWebhookNotification."Entity Key Value" := '772b7f9a-5463-f111-ba6c-8af3cd67cdee';
                    APIWebhookNotification."Entity ID" := APIWebhookNotification."Entity Key Value";
                    APIWebhookNotification."Last Modified Date Time" := CurrentDateTime();
                    APIWebhookNotification."Change Type" := APIWebhookNotification."Change Type"::Updated;
                    APIWebhookNotification.Insert();

                    Commit();

                    Sleep(5000);

                    // send notifications (front)
                    Codeunit.Run(Codeunit::"API Webhook Notification Send");
                end;
            }
Additional context

This bug is tied to reported customer issue case Number 2601271420000914

I will provide a fix for a bug
  • I will provide a fix for a bug

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with Codeunit 6154, API Webhook Notification Send, and trace IsNullUpdate through GenerateAggregateNotifications and ProcessNotifications. Reproduce the failure with the documented G/L Entry subscription, indirect read permission, and notification workflow. Done means notifications continue processing when the subscribing user lacks direct table read access, without preventing other events from being handled.

Written by the indexing model from the issue text.

Assessment

Domain
api, backend, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
52/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.