All skills
davidortinau avatar

/maui-secure-storage

@74acbe3

Add secure storage to .NET MAUI apps using SecureStorage.Default. Covers SetAsync, GetAsync, Remove, RemoveAll, platform setup (Android backup rules, iOS Keychain entitlements, Windows limits), common pitfalls, and a DI wrapper service for testability. USE FOR: "secure storage", "SecureStorage", "store token securely", "Keychain", "Android Keystore", "save secret", "encrypted storage", "store credentials", "sensitive data storage". DO NOT USE FOR: general file storage (use maui-file-handling), SQLite databases (use maui-sqlite-database), or authentication flows (use maui-authentication).

Use this Skill: https://skilld.dev/gh/davidortinau/maui-skills/maui-secure-storage

This session only. Nothing lands on disk.

referencessecure-storage-api.md

≈931 tokens on demand. Your agent reads this file only when SKILL.md points to it.

Secure Storage API Reference

API Surface

Use SecureStorage.Default (implements ISecureStorage):

// Store
await SecureStorage.Default.SetAsync("auth_token", token);

// Retrieve (returns null if not found)
string? token = await SecureStorage.Default.GetAsync("auth_token");

// Remove single key
bool removed = SecureStorage.Default.Remove("auth_token");

// Remove all
SecureStorage.Default.RemoveAll();

All values are strings only. Serialize complex data to JSON first.


Platform Setup

Android — Handle Auto Backup

Auto Backup can restore encrypted preferences to a new device where the encryption key is invalid, causing unrecoverable exceptions. Choose one approach:

Option A — Disable Auto Backup entirely:

In Platforms/Android/AndroidManifest.xml:

<application android:allowBackup="false" ...>

Option B — Exclude secure storage from backup:

  1. Create Platforms/Android/Resources/xml/auto_backup_rules.xml:
<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
  <exclude domain="sharedpref"
           path="${applicationId}.microsoft.maui.essentials.preferences.xml" />
</full-backup-content>
  1. Reference it in AndroidManifest.xml:
<application android:fullBackupContent="@xml/auto_backup_rules" ...>

iOS / Mac Catalyst — Enable Keychain

In Platforms/iOS/Entitlements.plist (and Platforms/MacCatalyst/Entitlements.plist):

<dict>
  <key>keychain-access-groups</key>
  <array>
    <string>$(AppIdentifierPrefix)com.yourcompany.yourapp</string>
  </array>
</dict>

Simulator only: Add the keychain access group matching your bundle ID. Remove it before building for physical devices or App Store submission — it is not needed there and can cause signing issues.

Windows

No setup required. Limits:

  • Key name: max 255 characters
  • Value: max 8 KB per setting
  • Composite storage: max 64 KB total

DI Wrapper Service for Testability

Define the interface

public interface ISecureStorageService
{
    Task SetAsync(string key, string value);
    Task<string?> GetAsync(string key);
    bool Remove(string key);
    void RemoveAll();
}

Implement against SecureStorage.Default

public class SecureStorageService : ISecureStorageService
{
    public Task SetAsync(string key, string value)
        => SecureStorage.Default.SetAsync(key, value);

    public async Task<string?> GetAsync(string key)
    {
        try
        {
            return await SecureStorage.Default.GetAsync(key);
        }
        catch (Exception)
        {
            // Corrupted value — clear and return null
            SecureStorage.Default.RemoveAll();
            return null;
        }
    }

    public bool Remove(string key)
        => SecureStorage.Default.Remove(key);

    public void RemoveAll()
        => SecureStorage.Default.RemoveAll();
}

Register in MauiProgram.cs

builder.Services.AddSingleton<ISecureStorageService, SecureStorageService>();

Inject into view models

public class LoginViewModel
{
    private readonly ISecureStorageService _secure;

    public LoginViewModel(ISecureStorageService secure)
    {
        _secure = secure;
    }

    public async Task SaveTokenAsync(string token)
    {
        await _secure.SetAsync("auth_token", token);
    }

    public async Task<string?> GetTokenAsync()
    {
        return await _secure.GetAsync("auth_token");
    }
}

Mock in tests

var mock = new Mock<ISecureStorageService>();
mock.Setup(s => s.GetAsync("auth_token"))
    .ReturnsAsync("test-token-value");

var vm = new LoginViewModel(mock.Object);

Source: SKILL.md on GitHub

1 warning15d4 checks · Risk SAFE
  • Gen Agent Trust Hub15d

    This skill provides secure storage implementation guidelines for .NET MAUI applications. It correctly identifies platform-specific pitfalls, such as Android backup corruption and iOS keychain persistence, and promotes security best practices including Dependency Injection wrappers and avoiding the logging of sensitive values.

  • Socket15d

    No alerts

  • Snyk15d

    Risk: LOW · No issues

  • Runlayer7mo

    1/1 file flagged

Signed by skilld at 74acbe3. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 months ago.

Steadyupdated 6 months ago

README badge

README badge for davidortinau/maui-skills/maui-secure-storage