diff --git a/src/main/java/com/cvsgo/controller/AuthController.java b/src/main/java/com/cvsgo/controller/AuthController.java index a1da5fe9..28f753c6 100644 --- a/src/main/java/com/cvsgo/controller/AuthController.java +++ b/src/main/java/com/cvsgo/controller/AuthController.java @@ -2,6 +2,7 @@ import com.cvsgo.dto.SuccessResponse; import com.cvsgo.dto.auth.LoginRequestDto; +import com.cvsgo.dto.auth.LoginResponseDto; import com.cvsgo.dto.auth.LogoutRequestDto; import com.cvsgo.dto.auth.TokenDto; import com.cvsgo.service.AuthService; @@ -23,7 +24,7 @@ public class AuthController { private final AuthService authService; @PostMapping("/login") - public SuccessResponse login(@RequestBody LoginRequestDto request) { + public SuccessResponse login(@RequestBody LoginRequestDto request) { return SuccessResponse.from(authService.login(request)); } @@ -34,7 +35,8 @@ public SuccessResponse logout(@RequestBody LogoutRequestDto request) { } @GetMapping("/tokens") - public SuccessResponse reissueToken(@RequestHeader("Authorization") String authorizationHeader) { + public SuccessResponse reissueToken( + @RequestHeader("Authorization") String authorizationHeader) { String refreshToken = authService.extractToken(authorizationHeader, TOKEN_TYPE); return SuccessResponse.from(authService.reissueToken(refreshToken)); } diff --git a/src/main/java/com/cvsgo/dto/auth/LoginResponseDto.java b/src/main/java/com/cvsgo/dto/auth/LoginResponseDto.java new file mode 100644 index 00000000..0aca6f5d --- /dev/null +++ b/src/main/java/com/cvsgo/dto/auth/LoginResponseDto.java @@ -0,0 +1,20 @@ +package com.cvsgo.dto.auth; + +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +public class LoginResponseDto { + + private Long userId; + + private TokenDto token; + + @Builder + public LoginResponseDto(Long userId, TokenDto token) { + this.userId = userId; + this.token = token; + } +} diff --git a/src/main/java/com/cvsgo/service/AuthService.java b/src/main/java/com/cvsgo/service/AuthService.java index ee55e84a..568aac0b 100644 --- a/src/main/java/com/cvsgo/service/AuthService.java +++ b/src/main/java/com/cvsgo/service/AuthService.java @@ -7,6 +7,7 @@ import static com.cvsgo.util.AuthConstants.TOKEN_TYPE; import com.cvsgo.dto.auth.LoginRequestDto; +import com.cvsgo.dto.auth.LoginResponseDto; import com.cvsgo.dto.auth.TokenDto; import com.cvsgo.entity.RefreshToken; import com.cvsgo.entity.User; @@ -38,7 +39,9 @@ public class AuthService { private final RefreshTokenRepository refreshTokenRepository; - public AuthService(@Value("${jwt.secret-key}") final String secretKey, UserRepository userRepository, PasswordEncoder passwordEncoder, RefreshTokenRepository refreshTokenRepository) { + public AuthService(@Value("${jwt.secret-key}") final String secretKey, + UserRepository userRepository, PasswordEncoder passwordEncoder, + RefreshTokenRepository refreshTokenRepository) { this.userRepository = userRepository; this.passwordEncoder = passwordEncoder; this.refreshTokenRepository = refreshTokenRepository; @@ -55,20 +58,26 @@ public AuthService(@Value("${jwt.secret-key}") final String secretKey, UserRepos * @throws UnauthorizedException 비밀번호가 일치하지 않는 경우 */ @Transactional - public TokenDto login(LoginRequestDto request) { - User user = userRepository.findByUserId(request.getEmail()).orElseThrow(() -> NOT_FOUND_USER); + public LoginResponseDto login(LoginRequestDto request) { + User user = userRepository.findByUserId(request.getEmail()) + .orElseThrow(() -> NOT_FOUND_USER); user.validatePassword(request.getPassword(), passwordEncoder); String accessToken = createAccessToken(user, key, ACCESS_TOKEN_TTL_MILLISECOND); RefreshToken refreshToken = RefreshToken.create(user, key, REFRESH_TOKEN_TTL_MILLISECOND); + TokenDto token = TokenDto.builder() + .accessToken(accessToken) + .refreshToken(refreshToken.getToken()) + .tokenType(TOKEN_TYPE) + .build(); + refreshTokenRepository.save(refreshToken); - return TokenDto.builder() - .accessToken(accessToken) - .refreshToken(refreshToken.getToken()) - .tokenType(TOKEN_TYPE) - .build(); + return LoginResponseDto.builder() + .userId(user.getId()) + .token(token) + .build(); } /** @@ -79,7 +88,8 @@ public TokenDto login(LoginRequestDto request) { */ @Transactional public void logout(String token) { - RefreshToken refreshToken = refreshTokenRepository.findByToken(token).orElseThrow(() -> UNAUTHORIZED_USER); + RefreshToken refreshToken = refreshTokenRepository.findByToken(token) + .orElseThrow(() -> UNAUTHORIZED_USER); refreshTokenRepository.delete(refreshToken); } @@ -92,27 +102,29 @@ public void logout(String token) { */ @Transactional public TokenDto reissueToken(String token) { - RefreshToken refreshToken = refreshTokenRepository.findByToken(token).orElseThrow(() -> UNAUTHORIZED_USER); + RefreshToken refreshToken = refreshTokenRepository.findByToken(token) + .orElseThrow(() -> UNAUTHORIZED_USER); refreshToken.updateToken(key, REFRESH_TOKEN_TTL_MILLISECOND); refreshTokenRepository.save(refreshToken); - String accessToken = createAccessToken(refreshToken.getUser(), key, ACCESS_TOKEN_TTL_MILLISECOND); + String accessToken = createAccessToken(refreshToken.getUser(), key, + ACCESS_TOKEN_TTL_MILLISECOND); return TokenDto.builder() - .accessToken(accessToken) - .refreshToken(refreshToken.getToken()) - .tokenType(TOKEN_TYPE) - .build(); + .accessToken(accessToken) + .refreshToken(refreshToken.getToken()) + .tokenType(TOKEN_TYPE) + .build(); } private String createAccessToken(User user, Key key, long ttlMillis) { long now = System.currentTimeMillis(); return Jwts.builder() - .setSubject(user.getUserId()) - .setIssuedAt(new Date(now)) - .setExpiration(new Date(now + ttlMillis)) - .signWith(key) - .compact(); + .setSubject(user.getUserId()) + .setIssuedAt(new Date(now)) + .setExpiration(new Date(now + ttlMillis)) + .signWith(key) + .compact(); } /** @@ -139,9 +151,9 @@ public String extractToken(String authorizationHeaderValue, String tokenType) { */ public void validateToken(String token) { Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(token); + .setSigningKey(key) + .build() + .parseClaimsJws(token); } @Transactional(readOnly = true) @@ -150,11 +162,11 @@ public Optional getLoginUser(String accessToken) { return Optional.empty(); } String email = Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(accessToken) - .getBody() - .getSubject(); + .setSigningKey(key) + .build() + .parseClaimsJws(accessToken) + .getBody() + .getSubject(); return userRepository.findByUserId(email); } diff --git a/src/test/java/com/cvsgo/controller/AuthControllerTest.java b/src/test/java/com/cvsgo/controller/AuthControllerTest.java index 9b650b74..c8869399 100644 --- a/src/test/java/com/cvsgo/controller/AuthControllerTest.java +++ b/src/test/java/com/cvsgo/controller/AuthControllerTest.java @@ -3,6 +3,7 @@ import com.cvsgo.argumentresolver.LoginUserArgumentResolver; import com.cvsgo.config.WebConfig; import com.cvsgo.dto.auth.LoginRequestDto; +import com.cvsgo.dto.auth.LoginResponseDto; import com.cvsgo.dto.auth.LogoutRequestDto; import com.cvsgo.dto.auth.TokenDto; import com.cvsgo.exception.ExceptionConstants; @@ -81,13 +82,17 @@ void respond_200_when_login_succeed() throws Exception { .email("abc@naver.com") .password("password1!") .build(); - TokenDto tokenDto = TokenDto.builder() - .accessToken(getSampleAccessToken()) - .refreshToken(getSampleRefreshToken()) - .tokenType(TOKEN_TYPE) - .build(); - - given(authService.login(any())).willReturn(tokenDto); + TokenDto token = TokenDto.builder() + .accessToken(getSampleAccessToken()) + .refreshToken(getSampleRefreshToken()) + .tokenType(TOKEN_TYPE) + .build(); + LoginResponseDto loginResponseDto = LoginResponseDto.builder() + .userId(1L) + .token(token) + .build(); + + given(authService.login(any())).willReturn(loginResponseDto); mockMvc.perform(post("/api/auth/login") .contentType(MediaType.APPLICATION_JSON) @@ -103,9 +108,10 @@ void respond_200_when_login_succeed() throws Exception { ), responseFields( fieldWithPath("timestamp").type(JsonFieldType.STRING).description("요청 시각"), - fieldWithPath("data.accessToken").type(JsonFieldType.STRING).description("액세스 토큰"), - fieldWithPath("data.refreshToken").type(JsonFieldType.STRING).description("리프레시 토큰"), - fieldWithPath("data.tokenType").type(JsonFieldType.STRING).description("토큰 종류") + fieldWithPath("data.userId").type(JsonFieldType.NUMBER).description("사용자 ID"), + fieldWithPath("data.token.accessToken").type(JsonFieldType.STRING).description("액세스 토큰"), + fieldWithPath("data.token.refreshToken").type(JsonFieldType.STRING).description("리프레시 토큰"), + fieldWithPath("data.token.tokenType").type(JsonFieldType.STRING).description("토큰 종류") ) )); } diff --git a/src/test/java/com/cvsgo/service/AuthServiceTest.java b/src/test/java/com/cvsgo/service/AuthServiceTest.java index caf2df4e..bba23a71 100644 --- a/src/test/java/com/cvsgo/service/AuthServiceTest.java +++ b/src/test/java/com/cvsgo/service/AuthServiceTest.java @@ -1,6 +1,7 @@ package com.cvsgo.service; import com.cvsgo.dto.auth.LoginRequestDto; +import com.cvsgo.dto.auth.LoginResponseDto; import com.cvsgo.dto.auth.TokenDto; import com.cvsgo.entity.RefreshToken; import com.cvsgo.entity.User; @@ -70,10 +71,10 @@ void should_get_tokens_when_succeed_to_login() { given(userRepository.findByUserId(loginRequestDto.getEmail())) .willReturn(Optional.of(user)); - TokenDto tokenDto = authService.login(loginRequestDto); + LoginResponseDto loginResponseDto = authService.login(loginRequestDto); - assertNotNull(tokenDto.getAccessToken()); - assertNotNull(tokenDto.getRefreshToken()); + assertNotNull(loginResponseDto.getToken().getAccessToken()); + assertNotNull(loginResponseDto.getToken().getRefreshToken()); }