Storing passwords directly in a table is a bad idea from a security point of view. For secure storage of passwords, the Service Password system table was previously used. In Business Central 15.0, it has been removed.
We are offered to use a new data type - Isolated Storage. Here we'll look at a practical example of using this functionality to store passwords securely.Suppose that we have a table and a setup page, the user should be able to save the password on the page so that it is used by the system somewhere in the process.To do this, we will write three main procedures: SetPassword(), GetPassword(), GetStorageKey(). Pay attention to the Acces property, it has the value Internal, which will not allow other extensions to access the password. We will also need a secret key in the GUID format by which the password will be stored. You can generate a key in any Online GUID Generator.
In our example, we will use Module DataScope.
table 50000 "General Setup"
{
DataClassification = CustomerContent;
Caption = 'General Setup';
Access = Internal;
fields
{
field(50000; "Primary Key"; Code[10])
{
DataClassification = CustomerContent;
Caption = 'Primary Key';
}
}
keys
{
key(PK; "Primary Key")
{
Clustered = true;
}
}
procedure SetPassword(NewPassword: Text)
var
EncryptionManagement: Codeunit "Cryptography Management";
begin
//Delete old password if exist
if IsolatedStorage.Contains(GetStorageKey(), DataScope::Module) then
IsolatedStorage.Delete((GetStorageKey(), DataScope::Module));
//Encrypt password if possible
if EncryptionManagement.IsEncryptionEnabled() and
EncryptionManagement.IsEncryptionPossible() then
NewPassword := EncryptionManagement.Encrypt(NewPassword);
//Set new password by storage key
IsolatedStorage.set(GetStorageKey(), NewPassword, DataScope::Module);
end;
procedure GetPassword(): Text
var
EncryptionManagement: Codeunit "Cryptography Management";
PasswordTxt: Text;
begin
//Check if password exist by storage key
if IsolatedStorage.Contains(GetStorageKey(), DataScope::Module) then begin
//Get exist password
IsolatedStorage.Get(GetStorageKey(), DataScope::Module, PasswordTxt);
//Decrypt password if possible
if EncryptionManagement.IsEncryptionEnabled() and
EncryptionManagement.IsEncryptionPossible() then
PasswordTxt := EncryptionManagement.Decrypt(PasswordTxt);
//Return password
exit(PasswordTxt);
end;
end;
local procedure GetStorageKey(): Text
var
StorageKeyTxt: Label '25edcb48-11b9-4e7d-8645-2c95b3156092', Locked = true;
begin
exit(StorageKeyTxt);
end;
}
Besides, we need a page where the user can specify a password.
page 50000 "General Setup"
{
PageType = Card;
ApplicationArea = All;
UsageCategory = Administration;
SourceTable = "General Setup";
Caption = 'General Setup';
layout
{
area(Content)
{
group(General)
{
field(PasswordTxt; PasswordTxt)
{
ApplicationArea = All;
ExtendedDatatype = Masked;
Caption = 'Password';
trigger OnValidate()
begin
SetPassword(PasswordTxt);
Commit();
end;
}
}
}
}
trigger OnOpenPage()
begin
Reset();
if not Get() then begin
Init();
Insert();
SetPassword('');
end else
PasswordTxt := '***';
end;
var
PasswordTxt: Text;
}
No comments:
Post a Comment