/// <summary> Refreshes jwt token</summary>
        public async Task <UserJwtResponseDto> RefreshJwtToken(RefreshJwtTokenDto refreshJwtTokenDto)
        {
            var validatedToken = _jwtAuthService.GetPrincipleFromToken(refreshJwtTokenDto.Token);

            if (validatedToken == null)
            {
                throw new AuthenticationException("Invalid token");
            }

            var tokenExpireDateUnix =
                long.Parse(validatedToken.Claims.Single(x => x.Type == JwtRegisteredClaimNames.Exp).Value);

            var tokenExpireDateUtc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
                                     .AddSeconds(tokenExpireDateUnix);

            if (tokenExpireDateUtc > DateTime.UtcNow)
            {
                throw new AuthenticationException("Token has not expired yet");
            }

            // get token id
            var jti = validatedToken.Claims.Single(x => x.Type == JwtRegisteredClaimNames.Jti).Value;

            var storedRefreshToken = await _context.RefreshTokens
                                     .FirstOrDefaultAsync(x => x.Token == refreshJwtTokenDto.RefreshToken);

            if (storedRefreshToken == null)
            {
                throw new AuthenticationException("Passed refresh token does not exist");
            }

            if (DateTime.UtcNow > storedRefreshToken.ExpireDate)
            {
                throw new AuthenticationException("Passed refresh token has expired");
            }

            if (storedRefreshToken.Invalidated)
            {
                throw new AuthenticationException("Passed refresh token is invalidated");
            }

            if (storedRefreshToken.IsUsed)
            {
                throw new AuthenticationException("Passed refresh token has been used");
            }

            if (storedRefreshToken.JwtId != jti)
            {
                throw new AuthenticationException("Passed refresh token does not match given JWT");
            }

            try
            {
                storedRefreshToken.IsUsed = true;
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateException ex)
            {
                throw new AppException("An error occurred during refreshing token", ex);
            }

            var userId = validatedToken.Claims.Single(x => x.Type == ClaimTypes.NameIdentifier).Value;

            var user = await GetById(userId);

            var userResponseDto = _mapper.Map <UserJwtResponseDto>(user);

            var jwtTokenDto = await _jwtAuthService.GetToken(user);

            userResponseDto.Token        = jwtTokenDto.Token;
            userResponseDto.RefreshToken = jwtTokenDto.RefreshToken;

            return(userResponseDto);
        }