Refresh Token Rotate란?
유효한 Refresh Token을 받으면 새로운 Access Token만 생성해 주는 것이 아닌 새로운 Refresh Token도 발급하여 로그인 유지 기간을 연장하는 작업
ReissueService 코드 수정
기존의 Access토큰만 발급해주는 코드
//make new JWT String newAccess = jwtUtil.createJwt("access", username, role, 600000L); //response response.setHeader("access", newAccess);RefreshToken까지 새로 발급해주는 코드
//make new JWT String newAccess = jwtUtil.createJwt("access", username, role, 600000L); String newRefresh = jwtUtil.createJwt("refresh", username, role, 86400000L); //response response.setHeader("access", newAccess); response.addCookie(createCookie("refresh", newRefresh));이제 이전에 발급되었던 RefreshToken을 사용하지 못하게 하기 위하여 블랙리스트 작업이 필요하다.
따라서 Refresh토큰을 관리하기 위한 레포지토리와 엔티티 등이 필요하다.
Refresh토큰의 서버차원 관리
Refresh 엔티티
public class Refresh { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String username; //어떤 유저의 토큰인지 구분자 private String refresh; //토큰 private String expiration; //만료시간 }Refresh 레포지토리
public interface RefreshRepository extends JpaRepository<RefreshEntity, Long> { Boolean existsByRefresh(String refresh); @Transactional void deleteByRefresh(String refresh); }로그인 성공 핸들러 수정
refresh객체 만들고 레포에 저장하는 메소드 추가
private void addRefreshEntity(String username, String refresh, Long expiredMs) { //refresh객체를 만들고 레포에 저장 Date date = new Date(System.currentTimeMillis() + expiredMs); Refresh refreshEntity = new Refresh(); refreshEntity.setUsername(username); refreshEntity.setRefresh(refresh); refreshEntity.setExpiration(date.toString()); refreshRepository.save(refreshEntity); }onAuthenticationSuccess메소드에 위에 작성한 메소드 추가
//토큰 생성 String accessToken = jwtUtil.createJwt("access", username, role, 600000L); //10분 String refreshToken = jwtUtil.createJwt("refresh", username, role, 86400000L); //24시간 //Refresh 토큰 저장 addRefreshEntity(username, refreshToken, 86400000L); //Access토큰은 헤더에, Refresh 토큰은 쿠키에 담아 보내기 response.setHeader("access", accessToken); response.addCookie(createCookie("refresh", refreshToken)); response.setStatus(HttpStatus.OK.value()); //200으로 프론트에 반환쳐주기
RefreshService 수정
기존의 refresh토큰 삭제 후 DB에 새로 생성한 refresh토큰 저장하는 로직 추가
private void addRefreshEntity(String username, String refresh, Long expiredMs) { //Refresh객체를 DB에 저장(블랙리스트관리) Date date = new Date(System.currentTimeMillis() + expiredMs); Refresh refreshEntity = new Refresh(); refreshEntity.setUsername(username); refreshEntity.setRefresh(refresh); refreshEntity.setExpiration(date.toString()); refreshRepository.save(refreshEntity); }기존의 reissue 메소드 수정
//make new JWT String newAccess = jwtUtil.createJwt("access", username, role, 600000L); String newRefresh = jwtUtil.createJwt("refresh", username, role, 86400000L); //Refresh 토큰 저장 DB에 기존의 Refresh 토큰 삭제 후 새 Refresh 토큰 저장 refreshRepository.deleteByRefresh(refresh); addRefreshEntity(username, newRefresh, 86400000L); //response response.setHeader("access", newAccess); response.addCookie(createCookie("refresh", newRefresh));
Reference