[Bug]: API Webhook notification are never sent when user do not have direct read access against table to be notified
Nobody has claimed this yet.
- 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
- Assigning indirect read permission on table G/L Entry (17) to an User
- Granting user capability to queue job
- Granting user capability to process webhook notifications
- Subscribing against
{businesscentralPrefix}/companies({id})/generalLedgerEntriesendpoint Creating Webhook Subscription - Using that user to post some Sales Invoice, producing G/L Entry and related Notification events
- Confirming processing notification
AL00006ZTappears (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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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