diff --git a/troubleshooting/250815_happybell80_JWT인증구현.md b/troubleshooting/250815_happybell80_JWT인증구현.md new file mode 100644 index 0000000..2e6147d --- /dev/null +++ b/troubleshooting/250815_happybell80_JWT인증구현.md @@ -0,0 +1,101 @@ +# 2025년 8월 15일 JWT 인증 구현 작업 + +## 오후 7시 20분 + +### JWT 토큰 인증 Frontend 구현 + +#### 문제 상황 +- Frontend가 JWT 토큰을 받아서 저장하지만 API 호출 시 전송하지 않음 +- X-User-Id 헤더만 보내서 누구나 다른 사용자로 위장 가능한 심각한 보안 취약점 +- 로그인 후 원래 페이지가 아닌 메인(/) 페이지로 리다이렉트되는 문제 + +#### 수정 내용 + +**1. chat-interface.tsx 수정** +```typescript +// 추가한 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. robing-api.ts 수정** +```typescript +// 함수 시그니처 변경 (토큰 파라미터 추가) +export async function sendMessage( + text: string, + token: string = '', + userId: string = 'test_user' +): Promise { + + // Authorization 헤더 추가 + const headers: Record = { + 'Content-Type': 'application/json', + 'X-User-Id': userId // 호환성을 위해 유지 + }; + + if (token) { + headers['Authorization'] = `Bearer ${token}`; + } +} +``` + +**3. auth-context.tsx 수정 (리다이렉트 개선)** +```typescript +// 로그인 시 현재 경로 저장 +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으로 복귀 ✅ + +#### 배포 +- Git commit & push 완료 +- Gitea Actions 자동 배포 진행 +- https://ro-being.com/game 에서 확인 가능 + +#### 다음 단계 +- Backend(robing-gateway)에서 JWT 토큰 검증 로직 추가 필요 +- 51124 서버 담당자와 협의하여 검증 구현 +- JWT_SECRET 환경변수 설정 및 공유 필요 + +#### 교훈 +- **보안 취약점은 즉시 수정**: 인증 토큰 미검증은 Critical 이슈 +- **단계적 접근이 효과적**: Frontend 먼저 수정 후 Backend 적용 +- **호환성 유지 중요**: X-User-Id 헤더 유지하면서 Authorization 추가 +- **사용자 경험 고려**: 로그인 후 원래 페이지로 돌아가도록 개선 \ No newline at end of file