63 lines
1.9 KiB
C#
63 lines
1.9 KiB
C#
using System.ComponentModel.DataAnnotations.Schema;
|
|
using System.Text;
|
|
using static System.Security.Cryptography.RandomNumberGenerator;
|
|
|
|
namespace Femto.Modules.Auth.Models;
|
|
|
|
public class LongTermSession
|
|
{
|
|
private static TimeSpan TokenTimeout { get; } = TimeSpan.FromDays(90);
|
|
private static TimeSpan RefreshBuffer { get; } = TimeSpan.FromDays(5);
|
|
|
|
public int Id { get; private set; }
|
|
|
|
public string Selector { get; private set; }
|
|
|
|
public byte[] HashedVerifier { get; private set; }
|
|
|
|
public DateTimeOffset Expires { get; private set; }
|
|
|
|
public Guid UserId { get; private set; }
|
|
|
|
[NotMapped]
|
|
public bool ExpiresSoon => this.Expires < DateTimeOffset.UtcNow + RefreshBuffer;
|
|
|
|
private LongTermSession() { }
|
|
|
|
public static (LongTermSession, string) Create(Guid userId)
|
|
{
|
|
var selector = GetString(
|
|
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789",
|
|
12
|
|
);
|
|
|
|
var verifier = GetString("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", 32);
|
|
|
|
using var sha256 = System.Security.Cryptography.SHA256.Create();
|
|
|
|
var longTermSession = new LongTermSession
|
|
{
|
|
Selector = selector,
|
|
HashedVerifier = ComputeHash(verifier),
|
|
UserId = userId,
|
|
Expires = DateTimeOffset.UtcNow + TokenTimeout,
|
|
};
|
|
|
|
return (longTermSession, verifier);
|
|
}
|
|
|
|
public bool Validate(string verifier)
|
|
{
|
|
if (this.Expires < DateTimeOffset.UtcNow)
|
|
return false;
|
|
|
|
return ComputeHash(verifier).SequenceEqual(this.HashedVerifier);
|
|
}
|
|
|
|
private static byte[] ComputeHash(string verifier)
|
|
{
|
|
using var sha256 = System.Security.Cryptography.SHA256.Create();
|
|
var hashedVerifier = sha256.ComputeHash(Encoding.UTF8.GetBytes(verifier));
|
|
return hashedVerifier;
|
|
}
|
|
}
|