Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
|
Caution Review failedThe pull request is closed. Walkthrough임시 하드코드 JWT를 폴백으로 사용하는 요청 인터셉터가 추가되고, Authorization 쿠키 유무를 상시 표시하는 UI 배지가 추가되었습니다. useOAuthToken 훅은 발급 실패 시 리다이렉트 대신 임시 토큰으로 폴백하고 URL의 code 쿼리 파라미터를 제거합니다. Changes
Sequence Diagram(s)sequenceDiagram
participant UI as UI/Component
participant API as apiClient
participant RI as Request Interceptor
participant S as Server
participant ResI as Response Interceptor
UI->>API: API 요청
API->>RI: 요청 인터셉션
alt Authorization 쿠키 없음
RI->>API: 헤더에 Bearer TEMP_ACCESS_TOKEN 설정
else 쿠키 있음
RI->>API: 헤더 변경 없이 진행 (브라우저가 쿠키 전송)
end
API->>S: 요청 전송
S-->>API: 응답
API->>ResI: 응답 인터셉션
ResI-->>UI: 응답 전달
sequenceDiagram
participant App as App
participant Hook as useOAuthToken
participant Auth as Auth Server
App->>Hook: 훅 초기화
alt loginTokenKey 없음
Hook->>Hook: 임시 토큰 사용 로깅
Hook->>Hook: URL 코드 파라미터 제거 (replaceState)
else loginTokenKey 있음
Hook->>Auth: 토큰 발급 시도
alt 성공
Auth-->>Hook: 토큰 반환
Hook->>Hook: 정상 흐름 유지
else 실패
Auth-->>Hook: 오류
Hook->>Hook: 임시 토큰 사용 로깅
Hook->>Hook: URL 코드 파라미터 제거 (replaceState)
end
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~15 minutes Possibly related PRs
Suggested labels
Poem
📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (1)
✨ Finishing Touches
🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (3)
src/components/common/TokenStatus.tsx (2)
7-18: 토큰 확인 로직을 API와 일치시키세요.
src/api/index.ts와 동일한 쿠키 파싱 로직을 사용하여 일관성을 보장하는 것이 좋습니다.공통 유틸리티 함수를 만들어 재사용하는 것을 제안합니다:
// src/utils/cookie.ts export const getCookie = (name: string): string | null => { const value = `; ${document.cookie}`; const parts = value.split(`; ${name}=`); if (parts.length === 2) return parts.pop()?.split(';').shift() || null; return null; };그리고 컴포넌트에서 사용:
+import { getCookie } from '@/utils/cookie'; const checkToken = () => { - const cookies = document.cookie.split(';'); - const hasAuthCookie = cookies.some(cookie => - cookie.trim().startsWith('Authorization=') - ); + const authCookie = getCookie('Authorization'); - if (hasAuthCookie) { + if (authCookie) { setTokenStatus('✅ Authorization 쿠키 있음'); } else { setTokenStatus('🔑 임시 토큰 사용 중'); } };
27-42: 인라인 스타일을 CSS 모듈이나 styled-components로 개선하세요.인라인 스타일보다는 더 유지보수가 쉬운 스타일링 방식을 사용하는 것이 좋습니다.
CSS 모듈을 사용한 예시:
// TokenStatus.module.css .tokenStatus { position: fixed; top: 10px; right: 10px; background: #333; color: white; padding: 8px 12px; border-radius: 4px; font-size: 12px; z-index: 9999; font-family: monospace; }+import styles from './TokenStatus.module.css'; - return ( - <div style={{ - position: 'fixed', - top: '10px', - right: '10px', - background: '#333', - color: 'white', - padding: '8px 12px', - borderRadius: '4px', - fontSize: '12px', - zIndex: 9999, - fontFamily: 'monospace' - }}> + return ( + <div className={styles.tokenStatus}> {tokenStatus} </div> );src/hooks/useOAuthToken.ts (1)
31-36: URL 정리 로직을 공통 함수로 분리하세요.동일한 URL 정리 로직이 성공/실패 케이스에서 반복됩니다.
다음과 같이 공통 함수로 분리할 수 있습니다:
+ const cleanupUrl = () => { + const newUrl = window.location.pathname; + window.history.replaceState({}, document.title, newUrl); + }; // 서버에 토큰 발급 요청 apiClient .post('/api/set-cookie', { loginTokenKey }, { withCredentials: true }) .then(response => { console.log('✅ 토큰 발급 성공:', response.data); - // URL에서 code 파라미터 제거 - const newUrl = window.location.pathname; - window.history.replaceState({}, document.title, newUrl); + cleanupUrl(); }) .catch(error => { console.error('❌ 토큰 발급 실패:', error); - // navigate('/'); console.log('💡 임시 토큰을 사용하여 계속 진행합니다.'); - // 에러 발생 시에도 임시 토큰으로 계속 진행 - // URL에서 code 파라미터 제거 - const newUrl = window.location.pathname; - window.history.replaceState({}, document.title, newUrl); + cleanupUrl(); });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/api/index.ts(1 hunks)src/components/common/TokenStatus.tsx(1 hunks)src/hooks/useOAuthToken.ts(1 hunks)
🧰 Additional context used
🪛 Gitleaks (8.27.2)
src/api/index.ts
18-18: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
17-18: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🔇 Additional comments (4)
src/api/index.ts (1)
42-52: 401 에러 처리 로직을 완성하거나 제거하세요.주석 처리된 리다이렉트 로직이 있어서 혼란을 줄 수 있습니다. 임시 토큰 사용 시나리오에서 401 에러 처리 방식을 명확히 정의해야 합니다.
현재 임시 토큰 사용 시 401 에러가 발생할 경우 어떻게 처리해야 하는지 확인이 필요합니다. 다음 중 하나를 선택해주세요:
- 임시 토큰도 실패 시 로그인 페이지로 리다이렉트
- 401 에러 처리를 상위 컴포넌트에 위임
- 다른 처리 방식
결정에 따라 해당 로직을 구현하거나 주석을 제거하겠습니다.
src/components/common/TokenStatus.tsx (1)
1-25: 컴포넌트 구현이 잘 되었습니다.토큰 상태를 실시간으로 모니터링하고 UI로 표시하는 기능이 잘 구현되었습니다. useEffect 클린업과 인터벌 관리도 적절합니다.
src/hooks/useOAuthToken.ts (2)
28-37: 에러 처리 개선이 잘 되었습니다.로그인 실패 시 임시 토큰으로 폴백하는 로직이 잘 구현되었고, URL 정리도 적절히 수행됩니다.
38-40: 로직이 올바르게 구현되었습니다.
loginTokenKey가 없는 경우에 대한 처리가 명확하게 추가되었습니다.
| // 임시 하드코딩된 토큰 (쿠키가 없을 때 사용) | ||
| const TEMP_ACCESS_TOKEN = | ||
| 'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjEsImlhdCI6MTc1NDM4MjY1MiwiZXhwIjoxNzU2OTc0NjUyfQ.BSGuoMWlrzc0oKgSJXHEycxdzzY9-e7gD4xh-wSDemc'; |
There was a problem hiding this comment.
하드코딩된 JWT 토큰을 환경변수로 이동하세요.
프로덕션 환경에서 JWT 토큰이 소스 코드에 하드코딩되어 있으면 보안 위험이 됩니다. 또한 정적 분석 도구에서도 이를 보안 위험으로 탐지하고 있습니다.
다음과 같이 환경변수로 이동하는 것을 권장합니다:
-// 임시 하드코딩된 토큰 (쿠키가 없을 때 사용)
-const TEMP_ACCESS_TOKEN =
- 'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjEsImlhdCI6MTc1NDM4MjY1MiwiZXhwIjoxNzU2OTc0NjUyfQ.BSGuoMWlrzc0oKgSJXHEycxdzzY9-e7gD4xh-wSDemc';
+// 임시 토큰 (쿠키가 없을 때 사용)
+const TEMP_ACCESS_TOKEN = import.meta.env.VITE_TEMP_ACCESS_TOKEN || '';📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // 임시 하드코딩된 토큰 (쿠키가 없을 때 사용) | |
| const TEMP_ACCESS_TOKEN = | |
| 'eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjEsImlhdCI6MTc1NDM4MjY1MiwiZXhwIjoxNzU2OTc0NjUyfQ.BSGuoMWlrzc0oKgSJXHEycxdzzY9-e7gD4xh-wSDemc'; | |
| // 임시 토큰 (쿠키가 없을 때 사용) | |
| const TEMP_ACCESS_TOKEN = import.meta.env.VITE_TEMP_ACCESS_TOKEN || ''; |
🧰 Tools
🪛 Gitleaks (8.27.2)
18-18: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.
(jwt)
17-18: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🤖 Prompt for AI Agents
In src/api/index.ts around lines 16 to 18, the JWT access token is hardcoded
which is a security risk; remove the literal string and instead read the token
from an environment variable (e.g. process.env.TEMP_ACCESS_TOKEN or a clearer
name like process.env.DEFAULT_ACCESS_TOKEN), validate that the env var exists at
startup and fail fast or log a clear error if missing, and ensure any defaults
are not sensitive values (no hardcoded fallback); update any documentation and
deployment configs to set the new env var.
| apiClient.interceptors.request.use( | ||
| config => { | ||
| // 쿠키에서 Authorization 확인 | ||
| const cookies = document.cookie.split(';'); | ||
| const hasAuthCookie = cookies.some(cookie => cookie.trim().startsWith('Authorization=')); | ||
|
|
||
| // 쿠키가 없으면 임시 토큰을 헤더에 추가 | ||
| if (!hasAuthCookie) { | ||
| console.log('🔑 쿠키가 없어서 임시 토큰을 헤더에 추가합니다.'); | ||
| config.headers.Authorization = `Bearer ${TEMP_ACCESS_TOKEN}`; | ||
| } else { | ||
| console.log('✅ Authorization 쿠키가 있어서 자동으로 전송됩니다.'); | ||
| } | ||
|
|
||
| return config; | ||
| }, | ||
| error => { | ||
| return Promise.reject(error); | ||
| }, | ||
| ); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
토큰 확인 로직을 개선하세요.
현재 구현에 다음과 같은 문제점이 있습니다:
- 쿠키 파싱 로직이 정확하지 않을 수 있습니다 (공백 처리 등)
- 빈 임시 토큰에 대한 검증이 없습니다
- 로깅이 과도할 수 있습니다
다음과 같이 개선된 구현을 제안합니다:
// Request 인터셉터: 쿠키가 없을 때 임시 토큰을 헤더에 추가
apiClient.interceptors.request.use(
config => {
- // 쿠키에서 Authorization 확인
- const cookies = document.cookie.split(';');
- const hasAuthCookie = cookies.some(cookie => cookie.trim().startsWith('Authorization='));
+ // 쿠키에서 Authorization 확인
+ const getCookie = (name: string) => {
+ const value = `; ${document.cookie}`;
+ const parts = value.split(`; ${name}=`);
+ if (parts.length === 2) return parts.pop()?.split(';').shift();
+ return null;
+ };
+
+ const authCookie = getCookie('Authorization');
- // 쿠키가 없으면 임시 토큰을 헤더에 추가
- if (!hasAuthCookie) {
- console.log('🔑 쿠키가 없어서 임시 토큰을 헤더에 추가합니다.');
- config.headers.Authorization = `Bearer ${TEMP_ACCESS_TOKEN}`;
+ // 쿠키가 없으면 임시 토큰을 헤더에 추가
+ if (!authCookie && TEMP_ACCESS_TOKEN) {
+ if (process.env.NODE_ENV === 'development') {
+ console.log('🔑 쿠키가 없어서 임시 토큰을 헤더에 추가합니다.');
+ }
+ config.headers.Authorization = `Bearer ${TEMP_ACCESS_TOKEN}`;
- } else {
- console.log('✅ Authorization 쿠키가 있어서 자동으로 전송됩니다.');
+ } else if (authCookie && process.env.NODE_ENV === 'development') {
+ console.log('✅ Authorization 쿠키가 있어서 자동으로 전송됩니다.');
}
return config;
},
error => {
return Promise.reject(error);
},
);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| apiClient.interceptors.request.use( | |
| config => { | |
| // 쿠키에서 Authorization 확인 | |
| const cookies = document.cookie.split(';'); | |
| const hasAuthCookie = cookies.some(cookie => cookie.trim().startsWith('Authorization=')); | |
| // 쿠키가 없으면 임시 토큰을 헤더에 추가 | |
| if (!hasAuthCookie) { | |
| console.log('🔑 쿠키가 없어서 임시 토큰을 헤더에 추가합니다.'); | |
| config.headers.Authorization = `Bearer ${TEMP_ACCESS_TOKEN}`; | |
| } else { | |
| console.log('✅ Authorization 쿠키가 있어서 자동으로 전송됩니다.'); | |
| } | |
| return config; | |
| }, | |
| error => { | |
| return Promise.reject(error); | |
| }, | |
| ); | |
| apiClient.interceptors.request.use( | |
| config => { | |
| // 쿠키에서 Authorization 확인 | |
| const getCookie = (name: string) => { | |
| const value = `; ${document.cookie}`; | |
| const parts = value.split(`; ${name}=`); | |
| if (parts.length === 2) return parts.pop()?.split(';').shift(); | |
| return null; | |
| }; | |
| const authCookie = getCookie('Authorization'); | |
| // 쿠키가 없으면 임시 토큰을 헤더에 추가 | |
| if (!authCookie && TEMP_ACCESS_TOKEN) { | |
| if (process.env.NODE_ENV === 'development') { | |
| console.log('🔑 쿠키가 없어서 임시 토큰을 헤더에 추가합니다.'); | |
| } | |
| config.headers.Authorization = `Bearer ${TEMP_ACCESS_TOKEN}`; | |
| } else if (authCookie && process.env.NODE_ENV === 'development') { | |
| console.log('✅ Authorization 쿠키가 있어서 자동으로 전송됩니다.'); | |
| } | |
| return config; | |
| }, | |
| error => { | |
| return Promise.reject(error); | |
| }, | |
| ); |
🤖 Prompt for AI Agents
In src/api/index.ts around lines 21 to 40, improve the token-checking logic:
parse document.cookie robustly by splitting on ';' then mapping/trimming each
pair and comparing key names exactly (e.g. cookie.split('=').map(s =>
s.trim())), check if config.headers and config.headers.Authorization already
exist before setting anything (ensure config.headers = config.headers || {}),
only set Authorization to `Bearer ${TEMP_ACCESS_TOKEN}` if no Authorization
cookie and TEMP_ACCESS_TOKEN is a non-empty string, and remove or reduce
console.log noise (use a single debug log or none); also preserve existing
header values and return config as before.
#️⃣연관된 이슈
📝작업 내용
스크린샷 (선택)
💬리뷰 요구사항(선택)
Summary by CodeRabbit
New Features
Improvements