AccessToken 재발급 프로세스

2021. 6. 28. 21:46Spring Security/Spring Boot Jwt with JPA and Redis

반응형

AccessToken 재발급은 앞에서 설명한 대로 만료시간을 짧게 설정하기 때문에 로그인을 자주 요청할 수 있게 된다. 이를 보완하기 위하여 AccessToken 이 만료되고, RefreshToken 이 유효하다면 사용자가 사이트를 이용하는 동안에 서버에서 자동으로 AccessToken을 재발급 함으로써 로그인 없이 사이트를 이용할 수 있도록 한다.

 

아래 그림은 AccessToken 재발급의 시퀀스다이어그램 입니다.

AccessToken 재발급 시퀀스다이어그램

JwtFilter

// AccessToken 재발급인 경우
if (!isValidAccessToken && isValidRefreshToken) {
	// AccessToken 재발급
	accessToken = reIssueAccessToken(refreshToken);

	// 쿠키 생성
	CookieUtil cookieUtil = new CookieUtil();
	httpServletResponse.addCookie(cookieUtil.createCookie(ACCESS_TOKEN_COOKIE_NAME, accessToken, "A"));

	// 재발급 AccessToken 유효성 체크
	isValidAccessToken = validateAccessToken(accessToken);
}

/**
 * AccessToken 재발급
 *
 * @param refreshToken
 * @return refreshToken 재발급 AccessToken
 */
private String reIssueAccessToken(String refreshToken) {
	HttpHeaders headers = new HttpHeaders();
	headers.setContentType(MediaType.APPLICATION_JSON);

	HttpEntity<String> request = new HttpEntity<>(refreshToken, headers);
	ResponseEntity<String> responseEntity = restTemplate.postForEntity( "http://localhost:10001/token/re-issue/access-token", request , String.class);

	return responseEntity.getBody();
}


/**
 * AccessToken 유효성 체크
 * 
 * @param accessToken
 * @return true or false
 */
private Boolean validateAccessToken(String accessToken) {
	return jwtUtil.validateToken(accessToken);
}

1. auth-server에 AccessToken을 재발급을 받는다.

2. accessTokenCookie를 생성한다.

3. 재발급받은 토큰의 유효성을 체크한다. 

 

TokenController.reIssueAccessToken

/**
 * AccessToken 재발급
 *
 * @param refreshToken Base64로 암호화된 값이므로 서비스 호출전 Decoding 처리 해얗 함
 * @return ResponseEntity<String> 재발급된 accessToken
 */
@PostMapping("/re-issue/access-token")
public ResponseEntity<String> reIssueAccessToken(@RequestBody String refreshToken) throws Exception {
	String accessToken = authService.generateAccessTokenFromRefreshToken(AES256Cipher.decrypt(refreshToken));

	return new ResponseEntity<>(accessToken, HttpStatus.OK);
}

refreshToken은 암호화되어 있으므로 서버에서 복호화 처리를 해줘야 한다.

 

AuthService.generateAccessTokenFromRefreshToken

@Override
public String generateAccessTokenFromRefreshToken(String refreshToken) throws Exception {
	String accessToken = null;

	// 전달받은 RefreshToken 정보로 Redis 서버에 저장된 사용자 ID 조회
	logger.debug("refreshToken({})", refreshToken);
	Optional<RefreshToken> token = Optional.ofNullable(refreshTokenRepository.findById(refreshToken)
			.orElseThrow(() -> new TokenNotFoundException("RefreshToken 이 존재하지 않습니다.")));

	// AccessToken 재밣행
	UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(token.get().getUsername(),
			AES256Cipher.decrypt(token.get().getPassword()));

	Authentication authentication = null;
	try {
		authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
	} catch (BadCredentialsException e) {
		throw new BadCredentialsException("[" + token.get().getUsername() + "] 사용자 정보가 존재 하지 않습니다.");
	}

	accessToken = tokenProvider.createToken(authentication);
	logger.debug("AccessToken({}) 이 정상적으로 발급 되었습니다.", accessToken);

	return accessToken;
}

1. Authentication 객체를 생성하기 위해서 Redis Server에 저장된 사용자 정보를 조회한다.

2. Authentication 객체를 생성한다.

3. TokenProvider에 토큰 생성을 요청한다.

4. 재발급된 accessToken을 반환한다.

 

 

반응형

'Spring Security > Spring Boot Jwt with JPA and Redis' 카테고리의 다른 글

RefreshToken 재발급 프로세스  (0) 2021.07.02
AccessToken 재발급 테스트  (0) 2021.07.02
로그인 테스트  (0) 2021.06.27
로그인 프로세스  (0) 2021.06.27
프로젝트 소개 및 설정  (0) 2021.06.27