Data Management with Isolated Storage in Microsoft Dynamics 365 Business Central

Guidelines for Partners

Securing sensitive information like passwords, tokens, and license information is a very important aspect of data management. In Business Central, ensuring data security can be achieved through Isolated Storage. In this blog post, we’ll guide you through a practical example of password management, showcasing how Isolated Storage adds an extra layer of protection.

 

What is Business Central’s Isolated Storage

Business Central  Isolated Storage serves as a secure repository for sensitive data, exclusively accessible within the application. By isolating data at the level of individual tenants, Isolated Storage enhances security significantly. The stored keys and values can be conveniently accessed through a dedicated API.

You also have the opportunity to specify a scope for accessing secrets. It can be Company, CompanyAndUser, Module, or User. In other words, the scope determines who can retrieve the data from the Isolated Storage.

 

Storing Password example

Here is a simple example of storing and retrieving passwords using Isolated Storage. In this scenario, the user provides a password and confirms it. A validation process verifies whether the entered password matches the confirmation. This example involves storing the password in Isolated Storage and retrieving it to compare it with the confirmed password.

table 50000 "Password"
{
    DataClassification = CustomerContent;
    Caption = ‘Password ';
    fields
    {
        field(1; "Primary Key"; Code[10])
        {
            DataClassification = CustomerContent;
            Caption = 'Primary Key';
        }
    }


    keys
    {
        key(PK; "Primary Key")
        {
            Clustered = true;
        }
    }
}


page 50000 "Password"

{
    PageType = Card;
    ApplicationArea = All;
    UsageCategory = Administration;
    SourceTable = "Password";

    layout
    {
        area(Content)
        {
            field(Password; Password)
            {
                ApplicationArea = All;
                Caption = 'Enter Password';
                ExtendedDatatype = Masked;

                trigger OnValidate()
                begin
                    PasswordStorage.SetPassword(Password);
                    Commit();
                end;
            }
            field(EnterPassword; EnterPassword)
            {
                ApplicationArea = All;
                Caption = 'Confirm Password';
                ExtendedDatatype = Masked;

                trigger OnValidate()
                begin
                    if PasswordStorage.ValidatePassword(EnterPassword) then
                        Message('Password Match. Congratulations!')
                    else
                        Error('Password did not match: Please try again');
                end;
            }

        }
    }
  
    var
        Password: Text;
        PasswordStorage: Codeunit "Password Storage";
        EnterPassword: Text;
}


codeunit 50000 "Password Storage"
{
    Access = Internal;


   procedure SetPassword(NewPassword: Text)
    begin
        // Verify if a password exists within Isolated Storage using its storage key.
        if IsolatedStorage.Contains('NewPassword', DataScope:: Module) 
  then
            IsolatedStorage.Delete('NewPassword', DataScope:: Module);
        // Store a new password in Isolated Storage
        IsolatedStorage.set('NewPassword', NewPassword, DataScope:: Module);
    end;


    local procedure GetPassword() NewPassword: Text
    begin
        // Verify if a password exists within Isolated Storage using its storage key.
        if IsolatedStorage.Contains('NewPassword', DataScope:: Module) then
        // Retrieve the existing password from Isolated Storage.
            IsolatedStorage.Get('NewPassword', DataScope:: Module, NewPassword);
    end;

    procedure ValidatePassword(EnteredPassword: Text): Boolean
    begin
        if EnteredPassword = GetPassword() then
            exit(true);
    end;

}

 

For an added layer of security, the “GetPassword” procedure is set to be local, restricting access solely within the codeunit. This measure decreases the risk of sensitive information being exposed through public functions. Additionally, the “Access” property of codeunit, set as “Internal”, ensures that other extensions cannot access the password, enhancing overall data security.

 

Business Central Isolated Storage

 

Conclusion

Microsoft Dynamics 365 Business Central’s Isolated Storage offers a strong solution for protecting important data, such as passwords. By providing a secure and separate space for storing confidential data, Isolated Storage ensures that it remains protected from unauthorized access by other applications.