public ActionResult <ResponseDto> RefreshToken([FromBody] TokenExchangeDto exchange)
        {
            if (!ModelState.IsValid)
            {
                // _accessor.HttpContext.Response.Headers.Add("Token-Expired", "none");
                return(BadRequest(InvalidModelErrors));
            }

            var handler = new JwtSecurityTokenHandler {
                MapInboundClaims = false
            };
            var param = _jwtConfig.Params;

            // when supplied false, the data are extracted from expired token.
            param.ValidateLifetime = false;
            var principal = handler.ValidateToken(exchange.AccessToken, param, out _);

            if (principal is null)
            {
                _response.MessageBody = "Invalid token";
                return(Unauthorized(_response));
            }

            var remote = _accessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();

            var username = principal.FindFirstValue(JwtRegisteredClaimNames.UniqueName);

            var user = _context.User
                       .Include(u => u.RefreshTokens)
                       .FirstOrDefault(u => u.Username == username);

            if (user is null || !user.HasValidRefreshToken(exchange.RefreshToken, remote))
            {
                _response.MessageBody = "Invalid token";
                return(Unauthorized(_response));
            }

            var refreshToken = _tokenFactory.GenerateToken();

            var tokenObj = GetJwt(PopulateClaims(user));

            user.RemoveRefreshToken(exchange.RefreshToken);
            user.AddRefreshToken(refreshToken, user.Id, remote);
            _context.User.Update(user);
            _context.SaveChanges();
            _response.ContentBody = new
            {
                jwt = tokenObj,
                refreshToken
            };
            return(Ok(_response));
        }
        public ActionResult <ResponseDto> Logout([FromBody] TokenExchangeDto exchange)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(InvalidModelErrors));
            }

            var handler = new JwtSecurityTokenHandler {
                MapInboundClaims = false
            };
            var param = _jwtConfig.Params;

            // when supplied false, the data are extracted from expired token.
            param.ValidateLifetime = false;
            var principal = handler.ValidateToken(exchange.AccessToken, param, out _);

            if (principal is null)
            {
                _response.MessageBody = "Invalid token";
                return(Unauthorized(_response));
            }

            var username = principal.FindFirstValue(JwtRegisteredClaimNames.UniqueName);

            var user = _context.User
                       .Include(u => u.RefreshTokens)
                       .FirstOrDefault(u => u.Username == username);
            var remote = _accessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();

            if (user is null || !user.HasValidRefreshToken(exchange.RefreshToken, remote))
            {
                _response.MessageBody = "Invalid token";
                return(Unauthorized(_response));
            }

            user.RemoveRefreshToken(exchange.RefreshToken);
            _context.User.Update(user);
            _context.SaveChanges();

            if (exchange.IsLogoutAll != null && (bool)exchange.IsLogoutAll)
            {
                _response.ContentBody = new { success = true }
            }
            ;

            return(Ok(_response));
        }