Skip to content

Commit

Permalink
Merge pull request #42 from tthisag246/fix/41
Browse files Browse the repository at this point in the history
[fix] auth의 누락된 예외 처리 및 Response Code 구체화
  • Loading branch information
win-luck authored Aug 30, 2024
2 parents f1f9b8b + 09ddeb6 commit 0a4e35e
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ public String getTokenFromAuthorizationHeader(String authorizationHeader) {
if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
return authorizationHeader.substring(7);
}
throw new AuthException(ResponseCode.BAD_REQUEST);
throw new AuthException(ResponseCode.USER_NO_AUTH_HEADER);
}

}
49 changes: 30 additions & 19 deletions src/main/java/gdsc/cau/puangbe/auth/external/KakaoProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import gdsc.cau.puangbe.auth.config.KakaoLoginProperties;
import gdsc.cau.puangbe.auth.dto.KakaoIDTokenPublicKeyList;
import gdsc.cau.puangbe.auth.dto.KakaoToken;
import gdsc.cau.puangbe.common.exception.AuthException;
import gdsc.cau.puangbe.common.util.ResponseCode;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.Cacheable;
Expand All @@ -12,6 +14,7 @@
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import org.springframework.web.reactive.function.client.WebClientResponseException;

@Component
@RequiredArgsConstructor
Expand All @@ -21,30 +24,38 @@ public class KakaoProvider {

// 카카오 인가 코드로 카카오 토큰 발급
public KakaoToken getTokenByCode(String code) {
return WebClient.create()
.post()
.uri(kakaoLoginProperties.getTokenUri())
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.body(BodyInserters.
fromFormData("grant_type", "authorization_code")
.with("client_id", kakaoLoginProperties.getClientId())
.with("redirect_uri", kakaoLoginProperties.getRedirectUri())
.with("code", code)
.with("client_secret", kakaoLoginProperties.getClientSecret()))
.retrieve()
.bodyToMono(KakaoToken.class)
.block();
try {
return WebClient.create()
.post()
.uri(kakaoLoginProperties.getTokenUri())
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.body(BodyInserters.
fromFormData("grant_type", "authorization_code")
.with("client_id", kakaoLoginProperties.getClientId())
.with("redirect_uri", kakaoLoginProperties.getRedirectUri())
.with("code", code)
.with("client_secret", kakaoLoginProperties.getClientSecret()))
.retrieve()
.bodyToMono(KakaoToken.class)
.block();
} catch (WebClientResponseException e) {
throw new AuthException(ResponseCode.USER_INVALID_KAKAO_CODE);
}
}

// 카카오 인증 서버로부터 카카오 ID 토큰 공개키 목록 조회하여 캐싱
@Cacheable(key = "'all'")
public KakaoIDTokenPublicKeyList getOIDCPublicKeyList() {
return WebClient.create()
.get()
.uri(kakaoLoginProperties.getPublicKeyUri())
.retrieve()
.bodyToMono(KakaoIDTokenPublicKeyList.class)
.block();
try {
return WebClient.create()
.get()
.uri(kakaoLoginProperties.getPublicKeyUri())
.retrieve()
.bodyToMono(KakaoIDTokenPublicKeyList.class)
.block();
} catch (WebClientResponseException e) {
throw new AuthException(ResponseCode.INTERNAL_SERVER_ERROR);
}
}

// 카카오 인증 서버로부터 카카오 ID 토큰 공개키 목록 재조회하여 캐싱
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ private KakaoIDTokenPayload extractPayloadFromTokenString(String token) {
// 온점(.)을 기준으로 헤더, 페이로드, 서명을 분리
String[] parts = token.split("\\.");
if (parts.length != 3) {
throw new AuthException(ResponseCode.BAD_REQUEST); // Invalid JWT token
throw new AuthException(ResponseCode.USER_INVALID_TOKEN); // Invalid JWT token
}

// 페이로드를 추출하여 Base64 방식으로 디코딩
Expand Down Expand Up @@ -100,7 +100,7 @@ private String extractHeaderKidFromTokenString(String token) {
// 온점(.)을 기준으로 헤더, 페이로드, 서명을 분리
String[] parts = token.split("\\.");
if (parts.length != 3) {
throw new AuthException(ResponseCode.BAD_REQUEST); // Invalid JWT token
throw new AuthException(ResponseCode.INTERNAL_SERVER_ERROR);
}

// 헤더을 추출하여 Base64 방식으로 디코딩
Expand All @@ -119,7 +119,7 @@ private KakaoIDTokenJWK getOIDCPublicKey(String kid, KakaoIDTokenPublicKeyList k
return kakaoIdTokenPublicKeyList.getKeys().stream()
.filter(kakaoIDTokenJWK -> kakaoIDTokenJWK.getKid().equals(kid))
.findFirst()
.orElseThrow(() -> new AuthException(ResponseCode.BAD_REQUEST)); // 일치하는 PK 없음
.orElseThrow(() -> new AuthException(ResponseCode.UNAUTHORIZED)); // 일치하는 PK 없음
}

// JWK로 RSA Public Key 생성
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/gdsc/cau/puangbe/common/util/ResponseCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ public enum ResponseCode {

// 400 Bad Request
BAD_REQUEST(HttpStatus.BAD_REQUEST, false, "잘못된 요청입니다."),
USER_NO_AUTH_HEADER(HttpStatus.BAD_REQUEST, false, "Authorization 헤더가 존재하지 않습니다."),
USER_INVALID_TOKEN(HttpStatus.BAD_REQUEST, false, "토큰이 형식이 올바르지 않습니다."),
USER_INVALID_KAKAO_CODE(HttpStatus.BAD_REQUEST, false, "인가 코드가 유효하지 않습니다."),

// 401 Unauthorized
UNAUTHORIZED(HttpStatus.UNAUTHORIZED, false, "인증되지 않은 사용자입니다."),

// 403 Forbidden
FORBIDDEN(HttpStatus.FORBIDDEN, false, "권한이 없습니다."),
REFRESH_TOKEN_EXPIRED(HttpStatus.FORBIDDEN, false, "리프레시 토큰이 만료되었습니다."),

// 404 Not Found
USER_NOT_FOUND(HttpStatus.NOT_FOUND, false, "사용자를 찾을 수 없습니다."),
Expand Down

0 comments on commit 0a4e35e

Please sign in to comment.