DOCS/journey/troubleshooting/250815_happybell80_JWT인증구현.md
Claude-51124 22557e7132 docs: 오래된 트러블슈팅 아카이브 및 구조 정리
- 7-8월 초기 구축 문서 12개를 _archive/troubleshooting/2025_07-08_initial_setup/로 이동
- book/300_architecture/390_human_in_the_loop_intent_learning.md를 journey/research/intent_classification/로 이동 (개발 여정 문서)
- 빈 폴더 제거 (journey/assets/*)
2025-11-17 14:06:05 +09:00

3.3 KiB

2025년 8월 15일 JWT 인증 구현 작업 (수정: 2025-08-28)

오후 7시 20분

JWT 토큰 인증 Frontend 구현

문제 상황

  • Frontend가 JWT 토큰을 받아서 저장하지만 API 호출 시 전송하지 않음
  • X-User-Id 헤더만 보내서 누구나 다른 사용자로 위장 가능한 심각한 보안 취약점
  • 로그인 후 원래 페이지가 아닌 메인(/) 페이지로 리다이렉트되는 문제

수정 내용

1. chat-interface.tsx 수정

// 추가한 import
import { useAuth } from '@/contexts/auth-context';
import { LoginDialog } from '@/components/login-dialog';

// 로그인 체크 추가
const { user, isAuthenticated } = useAuth();
const [showLoginDialog, setShowLoginDialog] = useState(false);

// handleSend 함수에 인증 체크
if (!isAuthenticated) {
  setShowLoginDialog(true);
  toast({
    title: "로그인 필요",
    description: "채팅을 하려면 먼저 로그인해주세요.",
    variant: "default",
  });
  return;
}

// 토큰과 userId 전달
const token = localStorage.getItem('token');
const userId = user?.id || user?.email || 'default';
const response = await sendMessage(input, token || '', userId);

2. robeing-api.ts 수정

// 함수 시그니처 변경 (토큰 파라미터 추가)
export async function sendMessage(
  text: string, 
  token: string = '', 
  userId: string = 'test_user'
): Promise<MessageResponse> {
  
  // Authorization 헤더 추가
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
    'X-User-Id': userId  // 호환성을 위해 유지
  };
  
  if (token) {
    headers['Authorization'] = `Bearer ${token}`;
  }
}

3. auth-context.tsx 수정 (리다이렉트 개선)

// 로그인 시 현재 경로 저장
const login = () => {
  const currentPath = window.location.pathname;
  localStorage.setItem('redirectAfterLogin', currentPath);
  
  // 전체 경로를 OAuth redirect_uri에 포함
  const redirectUrl = window.location.origin + currentPath;
  window.location.href = `${AUTH_SERVER_URL}/auth/gmail/login?redirect_uri=${encodeURIComponent(redirectUrl)}`;
};

// 로그인 성공 후 원래 페이지로 복귀
const redirectPath = localStorage.getItem('redirectAfterLogin');
if (redirectPath && redirectPath !== window.location.pathname) {
  localStorage.removeItem('redirectAfterLogin');
  window.location.href = redirectPath;
}

테스트 결과

  • 로그인하지 않은 상태에서 채팅 시도 시 로그인 다이얼로그 표시
  • 로그인 후 Authorization Bearer 토큰 헤더 전송 확인
  • /game 페이지에서 로그인 후 /game으로 복귀

배포

다음 단계

  • Backend(robeing-gateway)에서 JWT 토큰 검증 로직 추가 필요
  • 51124 서버 담당자와 협의하여 검증 구현
  • JWT_SECRET 환경변수 설정 및 공유 필요

교훈

  • 보안 취약점은 즉시 수정: 인증 토큰 미검증은 Critical 이슈
  • 단계적 접근이 효과적: Frontend 먼저 수정 후 Backend 적용
  • 호환성 유지 중요: X-User-Id 헤더 유지하면서 Authorization 추가
  • 사용자 경험 고려: 로그인 후 원래 페이지로 돌아가도록 개선