using System.Security.Cryptography; using Foxchat.Core.Utils; using NodaTime; namespace Foxchat.Identity.Database.Models; public class Token : BaseModel { public byte[] Hash { get; set; } = null!; public string[] Scopes { get; set; } = []; public Instant Expires { get; set; } // Tokens can be granted directly to applications with `client_credentials` public Ulid? AccountId { get; set; } public Account? Account { get; set; } public Ulid ApplicationId { get; set; } public Application Application { get; set; } = null!; public static (string, byte[]) Generate() { var token = CryptoUtils.RandomToken(48); var hash = SHA512.HashData(Convert.FromBase64String(token)); return (token, hash); } public static (string, Token) Create(Account? account, Application application, string[] scopes, Instant expires) { var (token, hash) = Generate(); return (token, new() { Hash = hash, Scopes = scopes, Expires = expires, Account = account, Application = application, }); } }