diff --git a/src/main/java/com/sanbosillok/sanbosillokserver/api/auth/controller/TokenController.java b/src/main/java/com/sanbosillok/sanbosillokserver/api/auth/controller/TokenController.java new file mode 100644 index 0000000..ab3f887 --- /dev/null +++ b/src/main/java/com/sanbosillok/sanbosillokserver/api/auth/controller/TokenController.java @@ -0,0 +1,23 @@ +package com.sanbosillok.sanbosillokserver.api.auth.controller; + +import com.sanbosillok.sanbosillokserver.api.auth.dto.AccessTokenResponse; +import com.sanbosillok.sanbosillokserver.api.auth.dto.RefreshTokenRequest; +import com.sanbosillok.sanbosillokserver.api.auth.service.TokenService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/token") +public class TokenController { + private final TokenService tokenService; + + @GetMapping("/refresh") + public AccessTokenResponse getNewToken(@RequestBody @Valid RefreshTokenRequest refreshTokenRequest) { + return tokenService.reIssueAccessToken(refreshTokenRequest.getRefreshToken()); + } +} diff --git a/src/main/java/com/sanbosillok/sanbosillokserver/api/auth/service/TokenService.java b/src/main/java/com/sanbosillok/sanbosillokserver/api/auth/service/TokenService.java new file mode 100644 index 0000000..387dff8 --- /dev/null +++ b/src/main/java/com/sanbosillok/sanbosillokserver/api/auth/service/TokenService.java @@ -0,0 +1,34 @@ +package com.sanbosillok.sanbosillokserver.api.auth.service; + +import com.sanbosillok.sanbosillokserver.api.auth.dto.AccessTokenResponse; +import com.sanbosillok.sanbosillokserver.api.member.domain.Member; +import com.sanbosillok.sanbosillokserver.api.member.repository.MemberRepository; +import com.sanbosillok.sanbosillokserver.config.jwt.JwtTokenProvider; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class TokenService { + private final JwtTokenProvider jwtTokenProvider; + private final MemberRepository memberRepository; + + public AccessTokenResponse reIssueAccessToken(String refreshToken) { + + if (refreshToken == null) { + throw new IllegalArgumentException("토큰이 비어있습니다."); + } + + if (jwtTokenProvider.isExpired(refreshToken)) { + throw new IllegalArgumentException("만료된 refresh token 입니다."); + } + + Long userId = jwtTokenProvider.getUserId(refreshToken); + Member member = memberRepository.findById(userId).orElseThrow(() -> new IllegalArgumentException("잘못된 token 형식입니다.")); + + String username = member.getUsername(); + String role = member.getRole().toString(); + + return new AccessTokenResponse(jwtTokenProvider.createAccessToken(username, role)); + } +} diff --git a/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/JwtTokenProvider.java b/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/JwtTokenProvider.java index 5de99d5..2e478c6 100644 --- a/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/JwtTokenProvider.java +++ b/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/JwtTokenProvider.java @@ -14,6 +14,9 @@ public class JwtTokenProvider { private final SecretKey secretKey; + @Value("${jwt.refresh-token.expire-length}") + private Long refreshTokenExpireLength; + @Value("${jwt.access-token.expire-length}") private Long accessTokenExpireLength; @@ -31,13 +34,16 @@ public String getRole(String token) { return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().get("role", String.class).split("_")[1]; } + public Long getUserId(String token) { + return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().get("id", Long.class); + } + public Boolean isExpired(String token) { return Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload().getExpiration().before(new Date()); } - public String createJwt(String username, String role) { - + public String createAccessToken(String username, String role) { return Jwts.builder() .claim("username", username) .claim("role", role) @@ -46,4 +52,14 @@ public String createJwt(String username, String role) { .signWith(secretKey) .compact(); } + + public String createRefreshToken(Long id) { + return Jwts.builder() + .claim("id", id) + .issuedAt(new Date(System.currentTimeMillis())) + .expiration(new Date(System.currentTimeMillis() + refreshTokenExpireLength)) + .signWith(secretKey) + .compact(); + } + } diff --git a/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/LoginFilter.java b/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/LoginFilter.java index 5cb8d38..c0eec65 100644 --- a/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/LoginFilter.java +++ b/src/main/java/com/sanbosillok/sanbosillokserver/config/jwt/LoginFilter.java @@ -46,6 +46,7 @@ public Authentication attemptAuthentication(HttpServletRequest request, HttpServ protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException { CustomUserDetails customUserDetails = (CustomUserDetails) authentication.getPrincipal(); + Long id = customUserDetails.getId(); String username = customUserDetails.getUsername(); Collection authorities = authentication.getAuthorities(); @@ -54,10 +55,11 @@ protected void successfulAuthentication(HttpServletRequest request, HttpServletR String role = auth.getAuthority(); - String token = jwtTokenProvider.createJwt(username, role); + String refreshToken = jwtTokenProvider.createRefreshToken(id); + String accessToken = jwtTokenProvider.createAccessToken(username, role); response.setContentType("application/json"); - response.getWriter().print(objectMapper.writeValueAsString(new LoginResponse(token, role))); + response.getWriter().print(objectMapper.writeValueAsString(new LoginResponse(refreshToken, accessToken, role))); } @Override diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 1b77d69..cd39b0f 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -15,4 +15,6 @@ spring: jwt: secret: ${JWT_SECRET} access-token: - expire-length: ${ACCESS_TOKEN_EXPIRED_TIME} \ No newline at end of file + expire-length: ${ACCESS_TOKEN_EXPIRED_TIME} + refresh-token: + expire-length: ${REFRESH_TOKEN_EXPIRED_TIME} \ No newline at end of file