1. 배경 및 문제 정의
서비스의 접근성을 높이기 위해 카카오 소셜 로그인 도입을 결정했습니다. 초기에는 Spring Security OAuth2 Client를 활용해 빠르게 기능을 구현하는 데 집중했으나, 구현 직후 다음과 같은 잠재적 보안 결함과 예외 상황들이 식별되었습니다.
- 토큰 노출: 인증 성공 후 JWT를 클라이언트에 전달할 때 URL 파라미터(
?token=...)를 사용. 이는 브라우저 히스토리나 서버 로그에 토큰이 남는 치명적인 보안 위협입니다. - 예외 처리 부재: 사용자가 로그인을 취소하거나 인증 오류 발생 시, 적절한 피드백 없이 500 에러가 발생하거나 기본 에러 페이지로 리다이렉트되는 문제.
- 데이터 충돌: 이미 일반 가입한 이메일 사용자가 동일한 이메일의 카카오 계정으로 로그인 시 데이터 무결성이 깨질 위험.
2. 원인 분석
근본적인 원인은 REST API 환경에 대한 고려 부족이었습니다.
- 전달 메커니즘의 한계:
SimpleUrlAuthenticationSuccessHandler의 기본 동작은 리다이렉트 기반이므로, 데이터를 안전하게 넘길 수 있는 수단이 제한적입니다. - 사용자 흐름 제어 미비: OAuth2 인증 흐름 중 발생하는 예외를 가로챌
FailureHandler가 등록되지 않았습니다. - 검증 로직 누락: 소셜 정보를 저장하는 단계에서 기존 가입자와의 이메일 중복 여부를 명시적으로 체크하지 않았습니다.
3. 해결 방안 검토
| 항목 | 방안 A (URL 파라미터) | 방안 B (HttpOnly 쿠키) |
|---|---|---|
| 보안성 | 매우 낮음 (로그 노출 위험) | 높음 (XSS 방어 및 로그 비노출) |
| 구현 난이도 | 매우 쉬움 | 보통 |
| 결론 | 폐기 | 최종 선택 |
4. 구현 과정
핵심 1: 보안 강화를 위한 SuccessHandler
JWT 토큰을 생성한 후, 클라이언트가 접근할 수 없는 HttpOnly 쿠키에 저장하여 보안을 강화했습니다.
@Override
public void onAuthenticationSuccess(...) throws IOException {
String token = jwtService.generateToken(email);
Cookie cookie = new Cookie("accessToken", token);
cookie.setPath("/");
cookie.setHttpOnly(true); // JavaScript 접근 방지
cookie.setMaxAge(3600);
response.addCookie(cookie);
getRedirectStrategy().sendRedirect(request, response, "/");
}
핵심 2: 계정 충돌 방지 (CustomOAuth2UserService)
이메일 중복 체크 로직을 추가하여 데이터 무결성을 확보했습니다.
User saveOrUpdate(OAuth2UserInfo userInfo) {
userRepository.findByEmail(userInfo.getEmail()).ifPresent(user -> {
if (!user.getProvider().equals("kakao")) {
throw new OAuth2AuthenticationException("이미 가입된 이메일입니다.");
}
});
// ... 저장 또는 업데이트 로직
}
트러블슈팅: URL 인코딩 이슈
실패 핸들러 테스트 중 에러 메시지가 URL 인코딩되는 방식이 환경마다 달라 테스트가 깨지는 현상이 있었습니다. 이를 해결하기 위해 구체적인 문자열 매칭 대신 파라미터 존재 여부와 리다이렉트 경로 위주의 검증으로 테스트 전략을 수정했습니다.
5. 개선 결과
- 보안성 향상:
HttpOnly쿠키 적용으로 토큰 탈취 위험 원천 차단. - UX 개선: 전용
FailureHandler도입으로 로그인 취소 시 사용자에게 명확한 에러 가이드 제공. - 안정성 확보: 중복 가입 방지 로직으로 DB 예외 상황 사전 방어 및 단위 테스트 100% 통과.
6. 회고
단순히 기능을 동작하게 만드는 단계를 넘어, 실제 운영 환경에서 발생할 수 있는 보안 위협과 예외 케이스를 설계 단계에서 고려하는 것이 얼마나 중요한지 다시금 확인하였다.
특히 소셜 로그인은 외부 플랫폼과의 연동인 만큼, 실패 시나리오(Edge Case)를 처리하는 것이 시스템 완성도의 핵심인거 같다.
'SSAC프로젝트' 카테고리의 다른 글
| 프론트 작업 [SSACFE-3] 사용자가 홈 화면에서 퀴즈를 풀 수 있습니다. (0) | 2026.04.23 |
|---|
