I suggested many times in the past to every partners I met and to all the attendees to my AL courses for Microsoft Italy that the way to store sensitive data in Dynamics 365 Business Central must be the Isolated Storage usage and not custom tricks on custom tables (see here) or using the old Service Password table (deprecated in Wave 2 release).
In this days, during an extension’s code checking for a partner where I had previosuly suggested those things, I see a license control checking like the following:
[EventSubscriber(ObjectType::Codeunit, Codeunit::LogInManagement, 'OnAfterLogInEnd', '', false, false)]
local procedure CheckLicense()
validLicense := false;
if IsolatedStorage.Get('LicenseKey',DataScope::Module,LicenseKeyValue) then
if not LicenseCheck(LicenseKeyValue) then
error('Your extension license is not valid')
//Valid license found
validLicense := true
if CheckLicensingLimit() then
error('You don''t have a license for this extension.');
local procedure LicenseCheck(LicenseKey: Text): Boolean
//custom license check here
local procedure CheckLicensingLimit(): Boolean
//if extension's installation date + N days are overdue, the extension cannot be used again
In this event subscriber, they search for a license key variable in the Isolated Storage. If the variable is found, a license check is performed (by calling the LicenseCheck procedure) and an error is thrown if the license is not valid.
At the same manner, an error is thrown also if the license key is not found in the Isolated Storage (the extension was never licensed by the user). For this task, they save in the Isolated Storage via an Install codeunit the date of the extension’s installation, then if this date + N limit days are overdue, an error is thrown (the customer has N days to acquire a license for this extension).
All is good as logic, but perform this license check in the OnAfterLogInEnd event and throwing an error here is absolutely to avoid. If your extension’s license check is failed (missing license or not valid license) you cannot login to that tenant!
My suggestion: throw an error from features of your extension or disable your extension’s business logic, but don’t throw errors from standard events in the application. N extensions can be installed on a tenant (you’re not alone) and you can’t block others if your extension’s license is not valid.
Another important thing to remember is the changements in secret management from Dynamics 365 Business Central Wave 2 release (explained here) related to Isolated Storage:
Accordingly to these changements, if you have an extension that works for Dynamics 365 Business Central SaaS and on-premise (same code) and you’re using the Isolated Storage to store secrets, you need to check if the encryption is enabled (always true for SaaS) and then save the secret accordingly.
So, a function that saves a license key to the Isolated Storage and that works for Dynamics 365 Business Central SaaS and on-premise will be as follows:
local procedure SaveLicense()
if not EncryptionEnabled() then