Isolated storage and secrets in AL
How AL extensions store secrets safely — IsolatedStorage scopes, Azure Key Vault integration, and the patterns for managing credentials in Business Central code.
Business Central extensions often need to store secrets — API keys for third-party services, tokens for OAuth flows, credentials for internal integrations. Hard-coding secrets in source or storing them in plain text records is unacceptable. AL provides IsolatedStorage and Azure Key Vault integration as the supported patterns.
IsolatedStorage. A key-value store scoped to extensions:
- Per-user, per-extension — secrets per user.
- Per-company, per-extension — shared across users in one company.
- Per-tenant, per-extension — global across companies and users.
The scope is selected at write time; reads respect the scope.
Basic usage.
IsolatedStorage.Set('ApiKey', 'secret-value', DataScope::Module);
if IsolatedStorage.Get('ApiKey', DataScope::Module, ApiKey) then
// use the key
The DataScope enum controls visibility:
User— per user.Company— per company.Module— per extension/tenant.
Encryption. Values stored in IsolatedStorage are encrypted at rest by BC. Only the extension that wrote can read; cross-extension access is restricted.
SecretText type. A specialised AL type for handling secrets:
- Values typed as
SecretTextinstead ofText. - Operations (string concatenation, conversion) restricted.
- Prevents accidental logging or display of secrets.
Use SecretText for API keys, tokens, passwords throughout code. The type's restrictions catch leaks at compile time.
Azure Key Vault integration. For organisations with formal secret management:
- Secrets live in Azure Key Vault.
- Extension reads via the AL Key Vault interface.
- Authentication via managed identity or service principal.
Pattern: secrets owned by IT in Key Vault, never directly handled by BC users.
Why not just store in a table?
- Encryption at rest is not always sufficient (depending on extension storage).
- Permissions on table columns can leak.
- Backup / restore can expose data.
- Audit trail on the table reveals access patterns.
IsolatedStorage and Key Vault are purpose-built for this.
Common patterns.
API key for external service:
procedure GetApiKey(): SecretText
var
ApiKeySecret: SecretText;
begin
if not IsolatedStorage.Get('ExternalApiKey', DataScope::Module, ApiKeySecret) then
Error('API key not configured');
exit(ApiKeySecret);
end;
OAuth refresh token per user:
procedure StoreRefreshToken(Token: SecretText)
begin
IsolatedStorage.Set('OAuthRefreshToken', Token, DataScope::User);
end;
Tenant-wide configuration secret:
procedure SetTenantSecret(Value: SecretText)
begin
IsolatedStorage.Set('TenantConfigSecret', Value, DataScope::Module);
end;
Migration from legacy code. Old extensions may store secrets in:
- Plain text table columns.
- Encrypted columns (worse than IsolatedStorage; rotation harder).
- Hard-coded literals.
Migration:
- Add IsolatedStorage write logic.
- Read from legacy location, write to IsolatedStorage on first run.
- Use IsolatedStorage subsequently.
- Remove legacy storage after grace period.
Permissions and access.
- Extension reads its own IsolatedStorage; another extension cannot.
- IsolatedStorage values not visible in the BC UI for admins to inspect (intentional).
- Key Vault values accessible only to extensions with explicit Key Vault permission.
Common pitfalls.
- Plain text secrets. Easy to type; security violation.
- Wrong scope. Storing per-user when it should be per-company; user changes cause secret loss.
- No rotation strategy. Secret in IsolatedStorage forever; compromise = full rotation needed.
- SecretText violated. Converting SecretText to Text to log it; leak.
- Backups include IsolatedStorage. Per Microsoft docs, IsolatedStorage included in BC backups; understand the implications.
Rotation.
- Periodic secret rotation per security policy.
- Extension must support rotation — accept new secret without code change.
- Configuration UI for admins to enter new secret; old secret retained briefly.
Auditing. IsolatedStorage doesn't have built-in access audit. For high-security needs:
- Wrap IsolatedStorage reads in a custom procedure that logs.
- Log to a dedicated audit table.
Strategic positioning. Secret handling in AL has matured significantly. Modern extensions use IsolatedStorage with SecretText typing throughout; Key Vault integration for enterprise secret management. Legacy extensions handling secrets in plain tables are technical debt and security risk. Audit extensions for secret-handling patterns; upgrade where needed. The cost is modest; the security and compliance benefits material.
Related guides
- Business Central CI/CD with AL-GoHow AL-Go for GitHub turns an AL extension repo into a build-test-deploy pipeline — secrets, environments, and continuous delivery.
- Business Central web servicesThe classic OData and SOAP web services in Business Central — how they differ from the v2.0 API, and when to use them.
- The AL debugger in Business Central — a deep diveHow the AL debugger works for developing Business Central extensions — VS Code integration, snapshot debugging, attaching to sessions, and the productivity tricks.
- The Business Central API and OData servicesHow external systems talk to Business Central — the v2.0 REST API, OData web services, bound actions, and call limits.
- AL events and integration patternsHow AL events let extensions hook into Business Central — business events, integration events, subscriber patterns, and what to avoid.