diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index 2170e2f..0056d0a 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -34,19 +34,14 @@ jobs: JAR=$(ls build/libs/*.jar | head -n 1) cp "$JAR" app.jar - - name: Create Firebase service account file - run: | - mkdir -p firebase - echo "${{ secrets.FCM }}" > firebase/tinybite_fcm.json - - name: Compute image name (change to lowercase) id: img run: echo "name=${{ env.REGISTRY }}/${GITHUB_REPOSITORY,,}" >> $GITHUB_OUTPUT - - name: Log in to GHCR + - name: Log in to GHCR registry: ${{ env.REGISTRY }} + uses: docker/login-action@v3 with: - registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GHCR_TOKEN }} diff --git a/src/main/java/ita/tinybite/domain/auth/dto/request/GoogleAndAppleSignupRequest.java b/src/main/java/ita/tinybite/domain/auth/dto/request/GoogleAndAppleSignupRequest.java index d84585a..27da6a0 100644 --- a/src/main/java/ita/tinybite/domain/auth/dto/request/GoogleAndAppleSignupRequest.java +++ b/src/main/java/ita/tinybite/domain/auth/dto/request/GoogleAndAppleSignupRequest.java @@ -2,6 +2,7 @@ import ita.tinybite.domain.user.constant.PlatformType; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; public record GoogleAndAppleSignupRequest( @NotBlank(message = "idToken은 필수입니다") @@ -12,7 +13,7 @@ public record GoogleAndAppleSignupRequest( String nickname, @NotBlank(message = "위치 정보 필수입니다") String location, - @NotBlank(message = "플랫폼정보는 필수입니다") + @NotNull(message = "플랫폼정보는 필수입니다") PlatformType platform ) { } diff --git a/src/main/java/ita/tinybite/domain/auth/service/AuthService.java b/src/main/java/ita/tinybite/domain/auth/service/AuthService.java index 4a3d504..76258ce 100644 --- a/src/main/java/ita/tinybite/domain/auth/service/AuthService.java +++ b/src/main/java/ita/tinybite/domain/auth/service/AuthService.java @@ -26,7 +26,9 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.oauth2.jwt.Jwt; import org.springframework.security.oauth2.jwt.JwtDecoder; +import org.springframework.security.oauth2.jwt.JwtException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -47,8 +49,8 @@ public class AuthService { private final JwtDecoder appleJwtDecoder; private final NicknameGenerator nicknameGenerator; -// @Value("${apple.client-id}") -// private String appleClientId; + @Value("${apple.client-id}") + private String appleClientId; @Value("${google.android-id}") private String googleAndroidId; @@ -224,10 +226,35 @@ private String getEmailFromIdToken(String idToken, PlatformType platformType, Lo } catch (GeneralSecurityException | IOException e) { throw BusinessException.of(AuthErrorCode.GOOGLE_LOGIN_ERROR); + } catch (Exception e) { + throw BusinessException.of(AuthErrorCode.INVALID_TOKEN); } } case APPLE -> { - //TODO Apple 구현 예정 + String clientId = appleClientId; + + try { + Jwt jwt = appleJwtDecoder.decode(idToken); + + if(!"https://appleid.apple.com".equals(jwt.getIssuer().toString())) { + throw BusinessException.of(AuthErrorCode.INVALID_TOKEN); + } + + String aud = jwt.getAudience().get(0); + if (!aud.equals(clientId)) { + throw BusinessException.of(AuthErrorCode.INVALID_TOKEN); + } + + Object emailObject = jwt.getClaims().get("email"); + if(emailObject == null) { + throw BusinessException.of(AuthErrorCode.NOT_EXISTS_EMAIL); + } + return emailObject.toString(); + } catch (JwtException e) { + throw BusinessException.of(AuthErrorCode.INVALID_TOKEN); + } catch (Exception e) { + throw BusinessException.of(AuthErrorCode.APPLE_LOGIN_ERROR); + } } } return null; diff --git a/src/main/java/ita/tinybite/global/config/FcmConfig.java b/src/main/java/ita/tinybite/global/config/FcmConfig.java index 9266cdc..00f156e 100644 --- a/src/main/java/ita/tinybite/global/config/FcmConfig.java +++ b/src/main/java/ita/tinybite/global/config/FcmConfig.java @@ -15,7 +15,6 @@ import jakarta.annotation.PostConstruct; import lombok.extern.slf4j.Slf4j; -import org.springframework.core.io.FileSystemResource; @Slf4j @Configuration @@ -31,7 +30,7 @@ public void initialize() { return; } try { - ClassPathResource resource = new ClassPathResource(fcmConfigPath); + ClassPathResource resource = new ClassPathResource(fcmConfigPath); try (InputStream stream = resource.getInputStream()) { FirebaseOptions options = FirebaseOptions.builder() .setCredentials(GoogleCredentials.fromStream(stream)) diff --git a/src/main/java/ita/tinybite/global/exception/errorcode/AuthErrorCode.java b/src/main/java/ita/tinybite/global/exception/errorcode/AuthErrorCode.java index 5e06b74..78851ec 100644 --- a/src/main/java/ita/tinybite/global/exception/errorcode/AuthErrorCode.java +++ b/src/main/java/ita/tinybite/global/exception/errorcode/AuthErrorCode.java @@ -16,7 +16,9 @@ public enum AuthErrorCode implements ErrorCode { GOOGLE_LOGIN_ERROR(HttpStatus.BAD_REQUEST, "GOOGLE_LOGIN_ERROR", "구글 로그인 중 에러가 발생했습니다."), APPLE_LOGIN_ERROR(HttpStatus.BAD_REQUEST, "APPLE_LOGIN_ERROR", "애플 로그인 중 에러가 발생했습니다."), - INVALID_PLATFORM(HttpStatus.BAD_REQUEST, "INVALID_PLATFORM", "올바른 플랫폼이 아닙니다. (Android, iOS)"); + INVALID_PLATFORM(HttpStatus.BAD_REQUEST, "INVALID_PLATFORM", "올바른 플랫폼이 아닙니다. (Android, iOS)"), + NOT_EXISTS_EMAIL(HttpStatus.BAD_REQUEST, "NOT_EXISTS_EMAIL", "애플 이메일이 존재하지 않습니다.") + ; private final HttpStatus httpStatus; private final String code; diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index 48436b3..80cd2c3 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -12,7 +12,7 @@ spring: jpa: show-sql: true hibernate: - ddl-auto: create-drop # 개발: update, 운영: validate 또는 none + ddl-auto: update # 개발: update, 운영: validate 또는 none data: redis: @@ -22,10 +22,3 @@ spring: kakao: client-id: ${KAKAO_CLIENT_ID} redirect-uri: ${KAKAO_REDIRECT_URI} - -naver: - client-id: ${NAVER_CLIENT_ID} - secret: ${NAVER_CLIENT_SECRET} - -fcm: - file_path: ${DEV_FCM_PATH} diff --git a/src/main/resources/application-local.yaml b/src/main/resources/application-local.yaml index c42b91e..0b5d0e2 100644 --- a/src/main/resources/application-local.yaml +++ b/src/main/resources/application-local.yaml @@ -28,13 +28,18 @@ spring: kakao: client-id: ${KAKAO_CLIENT_ID} redirect-uri: ${KAKAO_REDIRECT_URI} + +google: + android-id: ${GOOGLE_ANDROID_CLIENT_ID} + ios-id: ${GOOGLE_IOS_CLIENT_ID} -naver: - client-id: ${NAVER_CLIENT_ID} - secret: ${NAVER_CLIENT_SECRET} +google: + android-id: ${GOOGLE_ANDROID_CLIENT_ID} + ios-id: ${GOOGLE_IOS_CLIENT_ID} -fcm: - file_path: firebase/tinybite_fcm.json +#apple: +# client-id: ${APPLE_CLIENT_ID} +# logging: level: diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index b16e2c3..99a2f41 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -21,15 +21,15 @@ sms: api-key: ${SMS_API_KEY} api-secret: ${SMS_API_SECRET} +apple: + client-id: ${APPLE_CLIENT_ID} + +naver: + client-id: ${NAVER_CLIENT_ID} + secret: ${NAVER_CLIENT_SECRET} + fcm: + file_path: firebase/tinybite_fcm.json url: https://fcm.googleapis.com/v1/projects/${FCM_PROJECT_ID}/messages:send google_api: https://www.googleapis.com/auth/cloud-platform project_id: ${FCM_PROJECT_ID} - -google: - android-id: ${GOOGLE_ANDROID_CLIENT_ID} - ios-id: ${GOOGLE_IOS_CLIENT_ID} - -#apple: -# client-id: ${APPLE_CLIENT_ID} -#