public string EncodeRefreshToken(string username, DateTime expiryDate)
        {
            var user           = Read(username);
            var previousTokens = _dbContext.RefreshToken
                                 .Where(token => token.UserId == user.UserId && !token.IsRevoked)
                                 .ToList();

            foreach (var token in previousTokens)
            {
                token.IsRevoked = true;
            }
            var refreshToken = new RefreshToken
            {
                UserId = user.UserId,
                RefreshTokenExpiryDate = expiryDate,
                InitialVector          = PasswordHelper.GenerateInitialVector(),
                EncryptionKey          = PasswordHelper.GenerateAesKey(),
            };
            var refreshTokenEntity = _dbContext.RefreshToken.Add(refreshToken).Entity;

            _dbContext.RefreshToken.UpdateRange(previousTokens);
            _dbContext.SaveChanges();

            var refreshTokenClaims = new DecodedRefreshTokenClaims
            {
                Username   = username,
                ExpiryDate = expiryDate,
                Secret     = _dataProtector.Protect(BitConverter.GetBytes(refreshToken.RefreshTokenId)),
            };
            var encodedToken = String.Empty;

            using (var serializerStream = new MemoryStream())
            {
                Console.WriteLine($"{nameof(EncodeRefreshToken)} refreshTokenClaims: [{refreshTokenClaims.ToString()}]");
                _binaryFormatter.Serialize(serializerStream, refreshTokenClaims);
                encodedToken = Convert.ToBase64String(serializerStream.ToArray());
            }

            return(encodedToken);
        }
        public bool ValidateRefreshToken(string encodedRefreshToken, out DecodedRefreshTokenClaims refreshTokenClaims, out User user)
        {
            using (var deserializerStream = new MemoryStream(Convert.FromBase64String(encodedRefreshToken)))
            {
                refreshTokenClaims = (DecodedRefreshTokenClaims)_binaryFormatter.Deserialize(deserializerStream);
                user = null;

                if (refreshTokenClaims.ExpiryDate < DateTime.Now)
                {
                    return(false);
                }

                var username    = refreshTokenClaims.Username;
                var activeToken = _dbContext.RefreshToken
                                  .Include(rt => rt.User)
                                  .Where(rt => rt.User.Username == username && !rt.IsRevoked)
                                  .FirstOrDefault();
                user = activeToken.User;

                if (activeToken == null)
                {
                    return(false);
                }

                Console.WriteLine($"{nameof(ValidateRefreshToken)} refreshTokenClaims: [{refreshTokenClaims}]");
                Console.WriteLine($"{nameof(ValidateRefreshToken)} EncryptionKey: [{BitConverter.ToString(activeToken.EncryptionKey)}], InitialVector: [{BitConverter.ToString(activeToken.InitialVector)}]");
                var decryptedBytes  = _dataProtector.Unprotect(refreshTokenClaims.Secret);
                var decryptedSecret = BitConverter.ToInt64(decryptedBytes);
                Console.WriteLine($"{nameof(ValidateRefreshToken)} ActiveRefreshTokenId: {activeToken.RefreshTokenId}, DecryptedTokenId: {decryptedSecret}");

                if (activeToken.RefreshTokenId == decryptedSecret)
                {
                    return(true);
                }
            }

            return(false);
        }