namespace MinecraftDiscordBot; public class TimeoutTokenProvider : ITokenProvider { public TimeoutTokenProvider(int timeoutSeconds, ICipher? cipher = null) { _timeout = timeoutSeconds; _cipher = cipher ?? new AesCipher(); } private readonly ICipher _cipher; private readonly int _timeout; public bool VerifyToken(string token) { byte[] data; try { data = _cipher.Decrypt(Convert.FromHexString(token)); } catch (Exception e) { Program.LogError("TokenProvider", e); return false; } var when = DateTime.FromBinary(BitConverter.ToInt64(data, 0)); return when >= DateTime.UtcNow.AddSeconds(-_timeout); } public string GenerateToken() { var time = BitConverter.GetBytes(DateTime.UtcNow.ToBinary()); var key = Guid.NewGuid().ToByteArray(); var token = Convert.ToHexString(_cipher.Encrypt(time.Concat(key).ToArray())); return token; } } public interface ITokenProvider { string GenerateToken(); bool VerifyToken(string token); }