Files
tasteby/backend-java/src/main/java/com/tasteby/service/AuthService.java
joungmin ed076411ed fix: P4-3 인증 메시지 + 지도 cleanup/터치/접근성 (#266+#278)
#266 (인증):
- AuthService.loginGoogle: catch-all에서 e.getMessage() 노출 → "Invalid Google token"
  고정 메시지 + 상세는 log.warn (Google verifier 내부 오류 정보 누출 차단)

#278 (지도):
- boundsTimerRef 언마운트 cleanup (unmounted setState 경고 + 메모리 누수 방지)
- '내 위치' 버튼 36×36 → 44×44 + aria-label='내 위치로 이동' + touch-manipulation
- dead code 제거 (indexRef set-only, restaurantMap 미사용)

#277 (health) — 결함 모두 후속 분리 (deep health, version, 테스트, rate limit)

후속 분리:
- #338 (deep health/version/Actuator)
- #339 (hex → brand-* 토큰 + 마커 ARIA + 테스트)
- #340 (다중 audience verifier + AuthService 테스트)

Refs: #266 #277 #278
2026-06-15 14:25:53 +09:00

80 lines
3.2 KiB
Java

package com.tasteby.service;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.gson.GsonFactory;
import com.tasteby.domain.UserInfo;
import com.tasteby.security.JwtTokenProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.web.server.ResponseStatusException;
import java.util.Collections;
import java.util.Map;
@Service
public class AuthService {
private static final Logger log = LoggerFactory.getLogger(AuthService.class);
private final UserService userService;
private final JwtTokenProvider jwtProvider;
private final GoogleIdTokenVerifier verifier;
public AuthService(UserService userService, JwtTokenProvider jwtProvider,
@Value("${app.google.client-id}") String googleClientId) {
this.userService = userService;
this.jwtProvider = jwtProvider;
this.verifier = new GoogleIdTokenVerifier.Builder(
new NetHttpTransport(), GsonFactory.getDefaultInstance())
.setAudience(Collections.singletonList(googleClientId))
.build();
}
public Map<String, Object> loginGoogle(String idTokenString) {
try {
GoogleIdToken idToken = verifier.verify(idTokenString);
if (idToken == null) {
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid Google token");
}
GoogleIdToken.Payload payload = idToken.getPayload();
UserInfo user = userService.findOrCreate(
"google",
payload.getSubject(),
payload.getEmail(),
(String) payload.get("name"),
(String) payload.get("picture"));
// Convert to Map for JWT
Map<String, Object> userMap = Map.of(
"id", user.getId(),
"email", user.getEmail() != null ? user.getEmail() : "",
"nickname", user.getNickname() != null ? user.getNickname() : "",
"is_admin", user.isAdmin()
);
String accessToken = jwtProvider.createToken(userMap);
return Map.of("access_token", accessToken, "user", user);
} catch (ResponseStatusException e) {
throw e;
} catch (Exception e) {
// #266 — 외부에는 고정 메시지만, 상세는 로그로 (Google verifier 내부 네트워크/공개키
// 조회 실패 메시지가 클라이언트에 노출되지 않도록)
log.warn("Google token verification failed: {}", e.getMessage());
throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid Google token");
}
}
public UserInfo getCurrentUser(String userId) {
UserInfo user = userService.findById(userId);
if (user == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "User not found");
}
return user;
}
}