Skip to content

Commit

Permalink
feat: accessToken 재발급 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
Choi-JJunho committed Jan 9, 2024
1 parent 038b9ed commit c2709da
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import in.koreatech.koin.domain.auth.UserAuth;
import in.koreatech.koin.domain.user.dto.UserLoginRequest;
import in.koreatech.koin.domain.user.dto.UserLoginResponse;
import in.koreatech.koin.domain.user.dto.UserTokenRefreshRequest;
import in.koreatech.koin.domain.user.dto.UserTokenRefreshResponse;
import in.koreatech.koin.domain.user.model.User;
import in.koreatech.koin.domain.user.service.UserService;
import jakarta.validation.Valid;
Expand Down Expand Up @@ -31,4 +33,13 @@ public ResponseEntity<Void> logout(@UserAuth User user) {
userService.logout(user);
return ResponseEntity.ok().build();
}

@PostMapping("/user/refresh")
public ResponseEntity<UserTokenRefreshResponse> refresh(
@UserAuth User user,
@RequestBody @Valid UserTokenRefreshRequest request
) {
UserTokenRefreshResponse tokenGroupResponse = userService.refresh(user, request);
return ResponseEntity.ok().body(tokenGroupResponse);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package in.koreatech.koin.domain.user.dto;

import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import jakarta.validation.constraints.NotNull;

@JsonNaming(value = SnakeCaseStrategy.class)
public record UserTokenRefreshRequest(
@NotNull(message = "refresh_token을 입력해주세요.") String refreshToken
) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package in.koreatech.koin.domain.user.dto;

import com.fasterxml.jackson.annotation.JsonProperty;

public record UserTokenRefreshResponse(
@JsonProperty("token") String accessToken,
@JsonProperty("refresh_token") String refreshToken
) {

public static UserTokenRefreshResponse of(String accessToken, String refreshToken) {
return new UserTokenRefreshResponse(accessToken, refreshToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
import in.koreatech.koin.domain.auth.JwtProvider;
import in.koreatech.koin.domain.user.dto.UserLoginRequest;
import in.koreatech.koin.domain.user.dto.UserLoginResponse;
import in.koreatech.koin.domain.user.dto.UserTokenRefreshRequest;
import in.koreatech.koin.domain.user.dto.UserTokenRefreshResponse;
import in.koreatech.koin.domain.user.exception.UserNotFoundException;
import in.koreatech.koin.domain.user.model.User;
import in.koreatech.koin.domain.user.model.UserToken;
import in.koreatech.koin.domain.user.repository.UserRepository;
import in.koreatech.koin.domain.user.repository.UserTokenRepository;
import java.time.LocalDateTime;
import java.util.Objects;
import java.util.UUID;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
Expand Down Expand Up @@ -45,4 +48,14 @@ public UserLoginResponse login(UserLoginRequest request) {
public void logout(User user) {
userTokenRepository.deleteById(user.getId());
}

public UserTokenRefreshResponse refresh(User user, UserTokenRefreshRequest request) {
UserToken userToken = userTokenRepository.findById(user.getId())
.orElseThrow(() -> new IllegalArgumentException("refresh token이 존재하지 않습니다. request: " + request));
if (Objects.equals(userToken.getRefreshToken(), request.refreshToken())) {
throw new IllegalArgumentException("refresh token이 일치하지 않습니다. request: " + request);
}
String accessToken = jwtProvider.createToken(user);
return UserTokenRefreshResponse.of(accessToken, userToken.getRefreshToken());
}
}
51 changes: 51 additions & 0 deletions src/test/java/in/koreatech/koin/acceptance/AuthApiTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,55 @@ void userLogoutSuccess() {

Assertions.assertThat(token).isEmpty();
}

@Test
@DisplayName("사용자가 로그인 이후 refreshToken을 재발급한다")
void userRefreshToken() {
User user = User.builder()
.password("1234")
.nickname("주노")
.name("최준호")
.phoneNumber("010-1234-5678")
.userType(UserType.USER)
.email("[email protected]")
.isAuthed(true)
.isDeleted(false)
.build();

userRepository.save(user);

ExtractableResponse<Response> response = RestAssured
.given()
.log().all()
.body("""
{
"email": "[email protected]",
"password": "1234"
}
""")
.contentType(ContentType.JSON)
.when()
.log().all()
.post("/user/login")
.then()
.log().all()
.statusCode(HttpStatus.CREATED.value())
.extract();

RestAssured
.given()
.log().all()
.header("Authorization", "BEARER " + response.jsonPath().getString("token"))
.when()
.log().all()
.post("/user/logout")
.then()
.log().all()
.statusCode(HttpStatus.OK.value())
.extract();

Optional<UserToken> token = tokenRepository.findById(user.getId());

Assertions.assertThat(token).isEmpty();
}
}

0 comments on commit c2709da

Please sign in to comment.