69 lines
2.0 KiB
C#
69 lines
2.0 KiB
C#
using System.Text.Json;
|
|
using FruitBank.Common.Services;
|
|
|
|
namespace FruitBankHybrid.Services;
|
|
|
|
/// <summary>
|
|
/// MAUI implementation of ISecureCredentialService using SecureStorage.
|
|
/// </summary>
|
|
public sealed class MauiSecureCredentialService : ISecureCredentialService
|
|
{
|
|
private const string CredentialsKey = "FruitBank_UserCredentials";
|
|
private static readonly TimeSpan ExpirationDuration = TimeSpan.FromDays(2);
|
|
|
|
public async Task SaveCredentialsAsync(string email, string password)
|
|
{
|
|
var data = new SecureCredentialData
|
|
{
|
|
Email = email,
|
|
Password = password,
|
|
ExpiresAtUtc = DateTime.UtcNow.Add(ExpirationDuration)
|
|
};
|
|
|
|
var json = JsonSerializer.Serialize(data);
|
|
await SecureStorage.Default.SetAsync(CredentialsKey, json);
|
|
}
|
|
|
|
public async Task<StoredCredentials?> GetCredentialsAsync()
|
|
{
|
|
try
|
|
{
|
|
var json = await SecureStorage.Default.GetAsync(CredentialsKey);
|
|
if (string.IsNullOrEmpty(json))
|
|
return null;
|
|
|
|
var data = JsonSerializer.Deserialize<SecureCredentialData>(json);
|
|
if (data == null)
|
|
return null;
|
|
|
|
// Check expiration
|
|
if (DateTime.UtcNow > data.ExpiresAtUtc)
|
|
{
|
|
await ClearCredentialsAsync();
|
|
return null;
|
|
}
|
|
|
|
return new StoredCredentials(data.Email, data.Password);
|
|
}
|
|
catch
|
|
{
|
|
// If any error occurs (corrupted data, etc.), clear and return null
|
|
await ClearCredentialsAsync();
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public Task ClearCredentialsAsync()
|
|
{
|
|
SecureStorage.Default.Remove(CredentialsKey);
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
private sealed class SecureCredentialData
|
|
{
|
|
public string Email { get; set; } = string.Empty;
|
|
public string Password { get; set; } = string.Empty;
|
|
public DateTime ExpiresAtUtc { get; set; }
|
|
}
|
|
}
|