using System; using System.Globalization; using UnityEngine; namespace Vanguard.Auth { /// /// Access/refresh токены. В dev-сборке — PlayerPrefs; для релиза нужно /// защищённое хранилище (DPAPI/Keychain) через лаунчер или нативную обёртку. /// public sealed class TokenStore { private const string AccessKey = "vanguard.auth.access"; private const string RefreshKey = "vanguard.auth.refresh"; private const string AccessExpiresKey = "vanguard.auth.accessExpires"; private const string RefreshExpiresKey = "vanguard.auth.refreshExpires"; public string AccessToken { get; private set; } = string.Empty; public string RefreshToken { get; private set; } = string.Empty; public DateTimeOffset AccessExpiresAt { get; private set; } public DateTimeOffset RefreshExpiresAt { get; private set; } public bool HasRefreshToken => !string.IsNullOrEmpty(RefreshToken); public bool IsAccessExpired => AccessExpiresAt <= DateTimeOffset.UtcNow.AddSeconds(30); public TokenStore() { Load(); } public void Save( string accessToken, string refreshToken, DateTimeOffset accessExpiresAt, DateTimeOffset refreshExpiresAt) { AccessToken = accessToken ?? string.Empty; RefreshToken = refreshToken ?? string.Empty; AccessExpiresAt = accessExpiresAt; RefreshExpiresAt = refreshExpiresAt; PlayerPrefs.SetString(AccessKey, AccessToken); PlayerPrefs.SetString(RefreshKey, RefreshToken); PlayerPrefs.SetString(AccessExpiresKey, AccessExpiresAt.ToString("O", CultureInfo.InvariantCulture)); PlayerPrefs.SetString(RefreshExpiresKey, RefreshExpiresAt.ToString("O", CultureInfo.InvariantCulture)); PlayerPrefs.Save(); } public void Clear() { AccessToken = string.Empty; RefreshToken = string.Empty; AccessExpiresAt = default; RefreshExpiresAt = default; PlayerPrefs.DeleteKey(AccessKey); PlayerPrefs.DeleteKey(RefreshKey); PlayerPrefs.DeleteKey(AccessExpiresKey); PlayerPrefs.DeleteKey(RefreshExpiresKey); PlayerPrefs.Save(); } private void Load() { AccessToken = PlayerPrefs.GetString(AccessKey, string.Empty); RefreshToken = PlayerPrefs.GetString(RefreshKey, string.Empty); AccessExpiresAt = ParseDate(PlayerPrefs.GetString(AccessExpiresKey, string.Empty)); RefreshExpiresAt = ParseDate(PlayerPrefs.GetString(RefreshExpiresKey, string.Empty)); } private static DateTimeOffset ParseDate(string value) { return DateTimeOffset.TryParse( value, CultureInfo.InvariantCulture, DateTimeStyles.RoundtripKind, out var parsed) ? parsed : default; } } }