Skip to content

Commit

Permalink
[Feature] - 인증과정 예외처리 (#84)
Browse files Browse the repository at this point in the history
* feat: 로그인 응답에 데이터 추가, Response 생성 방식 캡슐화

- 카카오 닉네임, 프로필 이미지 경로

* refactor: RestClient 예외 처리 작성

* feat: 서버 내부 에러 처리 핸들러 작성

* feat: Swagger api 정보 추가

* fix: 최상위 예외 처리 코드 제거 개선
  • Loading branch information
Libienz authored Jul 22, 2024
1 parent 2ce3f22 commit a99c341
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package woowacourse.touroot.authentication.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -8,14 +13,26 @@
import org.springframework.web.bind.annotation.RestController;
import woowacourse.touroot.authentication.dto.LoginResponse;
import woowacourse.touroot.authentication.service.LoginService;
import woowacourse.touroot.global.exception.dto.ExceptionResponse;

@Tag(name = "로그인")
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/v1/login")
public class LoginController {

private final LoginService loginService;

@Operation(
summary = "카카오 로그인",
responses = {
@ApiResponse(
responseCode = "400",
description = "유효하지 않은 인가 코드로 로그인 요청을 했을 때",
content = @Content(schema = @Schema(implementation = ExceptionResponse.class))
)
}
)
@GetMapping("/oauth/kakao")
public ResponseEntity<LoginResponse> login(@RequestParam(name = "code") String authorizationCode) {
return ResponseEntity.ok()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
package woowacourse.touroot.authentication.dto;

public record LoginResponse(String accessToken) {
import io.swagger.v3.oas.annotations.media.Schema;
import woowacourse.touroot.member.domain.Member;

public record LoginResponse(
@Schema(description = "로그인된 유저의 닉네임") String nickname,
@Schema(description = "로그인된 유저의 프로필 이미지 경로") String profileImageUrl,
@Schema(description = "인가에 필요한 accessToken") String accessToken) {

public static LoginResponse of(Member member, String accessToken) {
return new LoginResponse(member.getNickname(), member.getProfileImageUri(), accessToken);
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,24 @@
package woowacourse.touroot.authentication.infrastructure;

import java.io.IOException;
import java.time.Duration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.ClientHttpRequestFactories;
import org.springframework.boot.web.client.ClientHttpRequestFactorySettings;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpRequest;
import org.springframework.http.HttpStatusCode;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestClient;
import woowacourse.touroot.authentication.dto.KakaoAccessTokenResponse;
import woowacourse.touroot.authentication.dto.OauthUserInformationResponse;
import woowacourse.touroot.global.exception.BadRequestException;
import woowacourse.touroot.global.exception.ClientException;

@Component
public class KakaoOauthClient {
Expand Down Expand Up @@ -55,6 +61,7 @@ public OauthUserInformationResponse requestUserInformation(String authorizationC
.uri(userInformationRequestUri)
.header(HttpHeaders.AUTHORIZATION, "Bearer " + kakaoAccessTokenResponse.accessToken())
.retrieve()
.onStatus(HttpStatusCode::isError, this::handleClientError)
.toEntity(OauthUserInformationResponse.class)
.getBody();
}
Expand All @@ -71,7 +78,15 @@ private KakaoAccessTokenResponse requestAccessToken(String authorizationCode) {
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.body(params)
.retrieve()
.onStatus(HttpStatusCode::isError, this::handleClientError)
.toEntity(KakaoAccessTokenResponse.class)
.getBody();
}

private void handleClientError(HttpRequest request, ClientHttpResponse response) throws IOException {
if (response.getStatusCode().is4xxClientError()) {
throw new BadRequestException("잘못된 로그인 요청입니다. 인가코드를 확인해주세요");
}
throw new ClientException("외부 서비스의 장애로 카카오로그인을 이용할 수 없습니다");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ public LoginResponse login(String code) {
Member member = memberRepository.findByKakaoId(userInformation.socialLoginId())
.orElseGet(() -> signUp(userInformation));

return new LoginResponse(tokenProvider.createToken(member));
return LoginResponse.of(member, tokenProvider.createToken(member));
}

private Member signUp(OauthUserInformationResponse userInformation) {
return memberRepository.save(
new Member(userInformation.socialLoginId(), userInformation.nickname(), userInformation.profileImage())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package woowacourse.touroot.global.exception;

public class ClientException extends RuntimeException {

public ClientException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,12 @@ public ResponseEntity<ExceptionResponse> handleMethodArgumentNotValidException(
return ResponseEntity.badRequest()
.body(data);
}

@ExceptionHandler(ClientException.class)
public ResponseEntity<ExceptionResponse> handleClientException(ClientException exception) {
log.error("CLIENT_EXCEPTION :: message = {}", exception.getMessage());

ExceptionResponse data = new ExceptionResponse(exception.getMessage());
return ResponseEntity.internalServerError().body(data);
}
}

0 comments on commit a99c341

Please sign in to comment.