Example #1
0
        public async Task <IActionResult> RefreshToken(RefreshTokenRequest request)
        {
            var(accessToken, refreshToken) = (request.AccessToken, request.RefreshToken);
            var tokenIsValid = ValidateToken(accessToken);

            if (!tokenIsValid)
            {
                throw new BadRequestException("The token is not valid");
            }

            var claimsPrincipal = GetTokenClaimsPrincipal(request.AccessToken);
            var expiryDateUnix  = long.Parse(claimsPrincipal.Claims.Single(c => c.Type == JwtRegisteredClaimNames.Exp).Value);
            var expiryDateUtc   = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(expiryDateUnix);
            var tokenHasExpired = DateTime.UtcNow > expiryDateUtc;

            if (!tokenHasExpired)
            {
                throw new BadRequestException("The token has not expired yet");
            }

            var userRefreshToken = _dbContext.RefreshTokens.SingleOrDefault(r => r.RefreshTokenValue == refreshToken);

            if (userRefreshToken == null)
            {
                throw new BadRequestException("The refresh token does not exists");
            }

            var refreshTokenHasExpired = DateTime.UtcNow > userRefreshToken.ExpiryDate;

            if (refreshTokenHasExpired)
            {
                throw new BadRequestException("The refresh token has expired");
            }

            if (userRefreshToken.Invalidated)
            {
                throw new BadRequestException("The refresh token has been invalidated");
            }

            var jtiClaimValue = claimsPrincipal.Claims.Single(c => c.Type == JwtRegisteredClaimNames.Jti).Value;
            var refreshTokenMatchWithTheAccessToken = jtiClaimValue == userRefreshToken.JwtId;

            if (!refreshTokenMatchWithTheAccessToken)
            {
                throw new BadRequestException("The refresh token does not match with the provided access token");
            }

            if (userRefreshToken.Used)
            {
                throw new BadRequestException("The refresh token has already been used");
            }

            userRefreshToken.Used = true;
            _dbContext.RefreshTokens.Update(userRefreshToken);
            await _dbContext.SaveChangesAsync();

            var userId = claimsPrincipal.Claims.Single(c => c.Type == "id").Value;
            var user   = await _userManager.FindByIdAsync(userId);

            return(GenerateUserAccessTokenAndRefreshToken(user));
        }