Skip to content

Using `Encryption` for your `MauiSettings`

Andreas edited this page Mar 21, 2024 · 2 revisions

This example shows you an approach to Secure and Encrypt your MauiSettings.

SettingsApp

This is a simple example of a SettingsApp.cs file holding sensitive data, like a user password.

 public partial class SettingsApp : MauiSettings<SettingsApp>
 {

     #region Properties
     static bool _settingsChanged = false;
     public static bool SettingsChanged
     {
         get => _settingsChanged;
         set
         {
             if (_settingsChanged == value) return;
             _settingsChanged = value;
         }
     }
     #endregion

     // Don't sync username and password => SkipForExport = true
     [MauiSetting(Name = nameof(Username), DefaultValue = "", Secure = true, Encrypt = true, SkipForExport = true)]
     public static string Username { get; set; } = string.Empty;

     [MauiSetting(Name = nameof(Password), DefaultValue = "", Secure = true, Encrypt = true, SkipForExport = true)]
     public static string Password { get; set; } = string.Empty;

     [MauiSetting(Name = nameof(PassPhrase), DefaultValue = "", Secure = true, SkipForExport = true)]
     public static string PassPhrase { get; set; } = string.Empty;

      #region Methods

      /// <summary>
      /// Creates a copy of the current <c>SettingsApp</c>
      /// </summary>
      /// <returns>Copy of the current <c>SettingsApp</c></returns>
      public static SettingsApp Copy()
      {
          SettingsApp app = new();
          app.LoadObjectSettings();
          return app;
      }

      #endregion
    }

App.xaml.cs

    public App(IServiceProvider serviceProvider)
    {
        InitializeComponent();

        // Load all unsecure settings first
        SettingsApp.LoadSettings();
        _ = Task.Run(async () =>
        {
            // Load first the passphrase, which is saved as `Secure`, but not `Encrypted`
            await SettingsApp.LoadSecureSettingAsync(settings => SettingsApp.PassPhrase);
            await SettingsApp.LoadSecureSettingsAsync(SettingsApp.PassPhrase);
        });

        MainPage = serviceProvider.GetRequiredService<AppShell>();
    }

First, the App loads all unsecure settings. This happens with the non-async method LoadSettings(). Afterwards, the App first loads the PassPhrase from the settings, then the Encrypted settings.

AuthPage

This ViewModel shows how to load the sensitive data on, for instance, an AuthPage.

        #region Properties

        [ObservableProperty]
        string emailAddress = string.Empty;

        [ObservableProperty]
        string password = string.Empty;

        [ObservableProperty]
        string? passPhrase;
        #endregion

        #region Ctor
        public AuthPageViewModel(IDispatcher dispatcher, IServiceProvider provider) : base(dispatcher, provider)
        {
            Dispatcher = dispatcher;
            LoadSettings();
        }
        #endregion

        #region Methods
        void LoadSettings()
        {
            IsLoading = true;
            PassPhrase = SettingsApp.PassPhrase;
            IsLoading = false;
        }
        #endregion

        #region Commands

        bool RefreshCommand_CanExecute() => !IsRefreshing;
        [RelayCommand(CanExecute = nameof(RefreshCommand_CanExecute))]
        async Task Refresh()
        {
            try
            {
                await SettingsApp.LoadSettingsAsync(key: PassPhrase);
                await DispatchManager.DispatchAsync(Dispatcher, () =>
                {
                    LoadSettings();
                    IsLoading = true;

                    EmailAddress = SettingsApp.Username;
                    Password = SettingsApp.Password;

                    IsLoading = false;
                });
#if DEBUG
                EventManager.Instance.LogEvent(new()
                {
                    SourceName = nameof(AuthPageViewModel),
                    Message = $"Refresh is done",
                });
#endif                                
            }
            catch (Exception exc)
            {
                // Log error
                EventManager.Instance.LogError(exc);
            }
            DispatchManager.Dispatch(Dispatcher, () => IsRefreshing = false);
        }
        #endregion
Clone this wiki locally