Conversation
Walkthrough이번 변경에서는 구글 및 네이버 소셜 로그인 기능이 추가되었습니다. 이를 위해 환경 변수, 인증 관련 API 모듈, UI 컴포넌트, WebView 기반 인증 플로우, 그리고 관련 의존성( Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant App
participant WebView/Browser
participant Naver/Google OAuth
participant Backend
User->>App: 소셜 로그인 버튼 클릭
App->>WebView/Browser: OAuth 인증 페이지 오픈
User->>Naver/Google OAuth: 로그인 및 동의
Naver/Google OAuth->>WebView/Browser: Redirect URI로 코드 전달
WebView/Browser->>App: 인증 코드 전달
App->>Backend: 인증 코드 전송 (POST)
Backend->>Naver/Google OAuth: 토큰/유저정보 요청
Naver/Google OAuth->>Backend: 토큰/유저정보 응답
Backend->>App: 유저 정보 응답
App->>User: 로그인 성공 처리
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
npm error Exit handler never called! ✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (5)
features/auth/ui/NaverLoginButton.tsx (1)
7-7: 네이밍 일관성 개선 제안KakaoLoginButton에서는
isShowWebView를 사용하는데, 여기서는showWebView를 사용하고 있습니다. 일관성을 위해 동일한 네이밍 컨벤션을 사용하는 것이 좋습니다.다음과 같이 수정하여 일관성을 맞추세요:
- const [showWebView, setShowWebView] = useState(false); + const [isShowWebView, setIsShowWebView] = useState(false);그리고 모든 참조를 업데이트하세요:
- setShowWebView(true); + setIsShowWebView(true); - setShowWebView(false); + setIsShowWebView(false); - <Modal visible={showWebView} animationType="slide" presentationStyle="pageSheet"> + <Modal visible={isShowWebView} animationType="slide" presentationStyle="pageSheet">features/auth/ui/GoogleLoginButton.tsx (1)
18-25: 에러 처리 중복 개선 고려현재 에러 발생 시
onLoginError콜백 호출과Alert.alert표시를 모두 수행하고 있습니다. 이는 사용자에게 중복된 에러 메시지를 보여줄 수 있습니다.다음과 같이 개선할 수 있습니다:
} else { onLoginError(result.error || "구글 로그인 중 오류가 발생했습니다."); - Alert.alert("로그인 실패", result.error || "구글 로그인 중 오류가 발생했습니다."); } } catch (error) { const errorMessage = error instanceof Error ? error.message : "알 수 없는 오류가 발생했습니다."; onLoginError(errorMessage); - Alert.alert("로그인 실패", errorMessage); }또는 에러 처리를 부모 컴포넌트에서 일관되게 처리하도록 구성할 수 있습니다.
features/auth/api/googleAuth.ts (2)
22-28: OAuth 스코프 하드코딩 개선 고려OAuth 스코프가 하드코딩되어 있습니다. 향후 확장성을 고려하면 설정 가능하도록 개선할 수 있습니다.
+const DEFAULT_SCOPES = "profile email"; + // OAuth URL const authUrl = `https://accounts.google.com/o/oauth2/v2/auth?` + `client_id=${GOOGLE_CLIENT_ID}` + `&redirect_uri=${encodeURIComponent(GOOGLE_REDIRECT_URI)}` + `&response_type=code` + - `&scope=${encodeURIComponent("profile email")}` + + `&scope=${encodeURIComponent(DEFAULT_SCOPES)}` + `&prompt=select_account`;
31-31: WebBrowser 세션 타임아웃 설정 고려WebBrowser 세션에 타임아웃이 설정되어 있지 않아 사용자가 무한정 대기할 수 있습니다.
Expo WebBrowser는 기본적으로 타임아웃을 지원하지 않지만, Promise.race를 사용하여 구현할 수 있습니다:
+// 타임아웃 설정 (30초) +const timeoutPromise = new Promise((_, reject) => { + setTimeout(() => reject(new Error("로그인 타임아웃")), 30000); +}); + // 기본 브라우저로 구글 로그인 페이지 열기 -const result = await WebBrowser.openAuthSessionAsync(authUrl, GOOGLE_REDIRECT_URI); +const result = await Promise.race([ + WebBrowser.openAuthSessionAsync(authUrl, GOOGLE_REDIRECT_URI), + timeoutPromise +]);features/auth/ui/NaverLoginWebView.tsx (1)
108-134: WebView 설정 최적화 고려WebView에 많은 설정이 적용되어 있는데, 일부는 불필요할 수 있습니다.
OAuth 플로우에 필요한 최소한의 설정만 유지하는 것을 권장합니다:
<WebView source={{ uri: authUrl }} onNavigationStateChange={handleNavigationChangeState} javaScriptEnabled={true} domStorageEnabled={true} - injectedJavaScript="window.ReactNativeWebView.postMessage('')" - startInLoadingState={false} - allowsBackForwardNavigationGestures={true} - allowsInlineMediaPlayback={true} - mediaPlaybackRequiresUserAction={false} - bounces={true} - scrollEnabled={true} - showsHorizontalScrollIndicator={false} - showsVerticalScrollIndicator={false} - decelerationRate="normal" - allowsFullscreenVideo={false} - allowsProtectedMedia={false} - dataDetectorTypes="none" {...(Platform.OS === "ios" && { allowsLinkPreview: false, - automaticallyAdjustContentInsets: false, })} />
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (8)
.env(1 hunks)app/index.tsx(1 hunks)features/auth/api/googleAuth.ts(1 hunks)features/auth/ui/GoogleLoginButton.tsx(1 hunks)features/auth/ui/KakaoLoginButton.tsx(2 hunks)features/auth/ui/NaverLoginButton.tsx(1 hunks)features/auth/ui/NaverLoginWebView.tsx(1 hunks)package.json(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
features/auth/ui/GoogleLoginButton.tsx (2)
features/auth/model/types.ts (1)
SocialLoginProps(9-12)features/auth/api/googleAuth.ts (1)
handleGoogleSignIn(70-92)
🔇 Additional comments (6)
package.json (1)
35-35: 의존성 추가 승인OAuth 인증 플로우를 지원하기 위한
expo-web-browser의존성 추가가 적절합니다..env (1)
3-7: 보안 설정 검증 완료
.env파일이.gitignore에 포함되어 있어 커밋되지 않음을 확인했습니다.
민감한 OAuth 인증 정보는 계속해서.env에 보관하시고, 배포 환경에서도 안전한 관리 정책을 유지해주세요.features/auth/ui/KakaoLoginButton.tsx (1)
7-7: 네이밍 개선 승인상태 변수명을
isShowWebView로 변경하여 boolean 값임을 명확히 하는 것이 좋은 개선입니다.features/auth/ui/NaverLoginButton.tsx (1)
29-46: 네이버 로그인 구현 승인모달 WebView를 사용한 네이버 로그인 구현이 잘 되어 있습니다. 적절한 에러 처리와 콜백 구조를 갖추고 있습니다.
features/auth/ui/GoogleLoginButton.tsx (2)
1-4: 임포트 및 의존성 확인 완료필요한 React Native 컴포넌트들과 타입, API 함수를 적절히 임포트하고 있습니다.
32-42: UI 구현 및 로딩 상태 관리 우수버튼의 로딩 상태에 따른 UI 변경 및 비활성화 처리가 잘 구현되어 있습니다. 사용자 경험을 고려한 좋은 구현입니다.
| EXPO_PUBLIC_NAVER_CLIENT_ID=tCdEIPDTDBnfdVRdRgoO | ||
| EXPO_PUBLIC_NAVER_CLIENT_SECRET=IX3znje6Hl | ||
| EXPO_PUBLIC_NAVER_REDIRECT_URI=https://dailysnap.xyz/api/auth/naver | ||
| EXPO_PUBLIC_GOOGLE_CLIENT_ID=735338487068-kh9kfnrrus8fdmucfek7996ml15jiell.apps.googleusercontent.com.apps.googleusercontent.com |
There was a problem hiding this comment.
Google 클라이언트 ID 수정 필요
Google 클라이언트 ID에 .apps.googleusercontent.com이 중복으로 포함되어 있습니다. 올바른 형식으로 수정해야 합니다.
다음과 같이 수정하세요:
-EXPO_PUBLIC_GOOGLE_CLIENT_ID=735338487068-kh9kfnrrus8fdmucfek7996ml15jiell.apps.googleusercontent.com.apps.googleusercontent.com
+EXPO_PUBLIC_GOOGLE_CLIENT_ID=735338487068-kh9kfnrrus8fdmucfek7996ml15jiell.apps.googleusercontent.com📝 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.
| EXPO_PUBLIC_GOOGLE_CLIENT_ID=735338487068-kh9kfnrrus8fdmucfek7996ml15jiell.apps.googleusercontent.com.apps.googleusercontent.com | |
| EXPO_PUBLIC_GOOGLE_CLIENT_ID=735338487068-kh9kfnrrus8fdmucfek7996ml15jiell.apps.googleusercontent.com |
🤖 Prompt for AI Agents
In the .env file at line 6, the Google client ID contains a duplicated suffix
'.apps.googleusercontent.com'. Remove the extra '.apps.googleusercontent.com' so
that the client ID ends with a single '.apps.googleusercontent.com' to correct
the format.
| // const { userInfo } = useAuth(); | ||
|
|
||
| useEffect(() => { | ||
| const timer = setTimeout(() => { | ||
| if (userInfo) { | ||
| // 로그인된 사용자면, 홈 네비게이션으로 이동 | ||
| router.replace("/(tabs)/home"); | ||
| } else { | ||
| // 로그인되지 않았으면 로그인 페이지로 이동 | ||
| router.replace("/login"); | ||
| } | ||
| router.replace("/(tabs)/home"); | ||
| // if (userInfo) { | ||
| // // 로그인된 사용자면, 홈 네비게이션으로 이동 | ||
| // router.replace("/(tabs)/home"); | ||
| // } else { | ||
| // // 로그인되지 않았으면 로그인 페이지로 이동 | ||
| // router.replace("/login"); | ||
| // } | ||
| }, 100); | ||
|
|
||
| return () => clearTimeout(timer); | ||
| }, [userInfo, router]); | ||
| }, [router]); |
There was a problem hiding this comment.
인증 우회에 대한 우려사항
사용자 인증 로직이 주석 처리되어 모든 사용자가 로그인 없이 홈으로 이동합니다. 이는 의도된 변경인지 확인이 필요합니다.
만약 개발 중 임시 변경이라면, 배포 전 반드시 인증 로직을 복원해야 합니다.
인증이 필요한 앱이라면 다음과 같이 복원하세요:
- // const { userInfo } = useAuth();
+ const { userInfo } = useAuth();
- router.replace("/(tabs)/home");
- // if (userInfo) {
- // // 로그인된 사용자면, 홈 네비게이션으로 이동
- // router.replace("/(tabs)/home");
- // } else {
- // // 로그인되지 않았으면 로그인 페이지로 이동
- // router.replace("/login");
- // }
+ if (userInfo) {
+ // 로그인된 사용자면, 홈 네비게이션으로 이동
+ router.replace("/(tabs)/home");
+ } else {
+ // 로그인되지 않았으면 로그인 페이지로 이동
+ router.replace("/login");
+ }
- }, [router]);
+ }, [router, userInfo]);📝 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 { userInfo } = useAuth(); | |
| useEffect(() => { | |
| const timer = setTimeout(() => { | |
| if (userInfo) { | |
| // 로그인된 사용자면, 홈 네비게이션으로 이동 | |
| router.replace("/(tabs)/home"); | |
| } else { | |
| // 로그인되지 않았으면 로그인 페이지로 이동 | |
| router.replace("/login"); | |
| } | |
| router.replace("/(tabs)/home"); | |
| // if (userInfo) { | |
| // // 로그인된 사용자면, 홈 네비게이션으로 이동 | |
| // router.replace("/(tabs)/home"); | |
| // } else { | |
| // // 로그인되지 않았으면 로그인 페이지로 이동 | |
| // router.replace("/login"); | |
| // } | |
| }, 100); | |
| return () => clearTimeout(timer); | |
| }, [userInfo, router]); | |
| }, [router]); | |
| const { userInfo } = useAuth(); | |
| useEffect(() => { | |
| const timer = setTimeout(() => { | |
| if (userInfo) { | |
| // 로그인된 사용자면, 홈 네비게이션으로 이동 | |
| router.replace("/(tabs)/home"); | |
| } else { | |
| // 로그인되지 않았으면 로그인 페이지로 이동 | |
| router.replace("/login"); | |
| } | |
| }, 100); | |
| return () => clearTimeout(timer); | |
| }, [router, userInfo]); |
🤖 Prompt for AI Agents
In app/index.tsx between lines 9 and 24, the user authentication logic is
commented out, causing all users to be redirected to the home page without
login. To fix this, restore the authentication check by uncommenting the
userInfo usage and conditionally redirect users to the home page if logged in or
to the login page if not. Ensure this logic is active before deployment to
enforce proper authentication flow.
| const GOOGLE_CLIENT_ID = process.env.EXPO_PUBLIC_GOOGLE_CLIENT_ID ?? ""; | ||
| const GOOGLE_REDIRECT_URI = process.env.EXPO_PUBLIC_GOOGLE_REDIRECT_URI ?? ""; | ||
| const SERVER_BASE_URL = process.env.EXPO_PUBLIC_SERVER_BASE_URL ?? ""; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
환경변수 검증 추가 필요
환경변수들이 빈 문자열로 초기화되어 있지만, 실제 런타임에서 이 값들이 유효한지 검증하는 로직이 없습니다.
다음과 같이 환경변수 검증을 추가하는 것을 권장합니다:
const GOOGLE_CLIENT_ID = process.env.EXPO_PUBLIC_GOOGLE_CLIENT_ID ?? "";
const GOOGLE_REDIRECT_URI = process.env.EXPO_PUBLIC_GOOGLE_REDIRECT_URI ?? "";
const SERVER_BASE_URL = process.env.EXPO_PUBLIC_SERVER_BASE_URL ?? "";
+// 환경변수 검증
+if (!GOOGLE_CLIENT_ID || !GOOGLE_REDIRECT_URI || !SERVER_BASE_URL) {
+ throw new 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.
| const GOOGLE_CLIENT_ID = process.env.EXPO_PUBLIC_GOOGLE_CLIENT_ID ?? ""; | |
| const GOOGLE_REDIRECT_URI = process.env.EXPO_PUBLIC_GOOGLE_REDIRECT_URI ?? ""; | |
| const SERVER_BASE_URL = process.env.EXPO_PUBLIC_SERVER_BASE_URL ?? ""; | |
| const GOOGLE_CLIENT_ID = process.env.EXPO_PUBLIC_GOOGLE_CLIENT_ID ?? ""; | |
| const GOOGLE_REDIRECT_URI = process.env.EXPO_PUBLIC_GOOGLE_REDIRECT_URI ?? ""; | |
| const SERVER_BASE_URL = process.env.EXPO_PUBLIC_SERVER_BASE_URL ?? ""; | |
| // 환경변수 검증 | |
| if (!GOOGLE_CLIENT_ID || !GOOGLE_REDIRECT_URI || !SERVER_BASE_URL) { | |
| throw new Error("구글 로그인에 필요한 환경변수가 설정되지 않았습니다."); | |
| } |
🤖 Prompt for AI Agents
In features/auth/api/googleAuth.ts around lines 4 to 6, the environment
variables are assigned default empty strings without runtime validation. Add
validation logic after these assignments to check if any of the variables are
empty or invalid, and throw an error or handle the case appropriately to ensure
the app does not proceed with missing critical configuration.
| export async function exchangeGoogleCodeForUserInfo(code: string) { | ||
| try { | ||
| const response = await axios.post(`${SERVER_BASE_URL}/api/auth/google`, { code }); | ||
| return response.data; | ||
| } catch (error) { | ||
| console.error("Google Token Exchange Error:", error); | ||
| throw error; | ||
| } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
백엔드 API 에러 처리 개선 필요
현재 백엔드 API 호출에서 HTTP 상태 코드별 에러 처리가 부족합니다.
export async function exchangeGoogleCodeForUserInfo(code: string) {
try {
const response = await axios.post(`${SERVER_BASE_URL}/api/auth/google`, { code });
+
+ if (response.status !== 200) {
+ throw new Error(`서버 응답 오류: ${response.status}`);
+ }
+
return response.data;
} catch (error) {
console.error("Google Token Exchange Error:", error);
+
+ if (axios.isAxiosError(error)) {
+ if (error.response?.status === 401) {
+ throw new Error("인증에 실패했습니다.");
+ } else if (error.response?.status === 500) {
+ throw new Error("서버 오류가 발생했습니다.");
+ }
+ }
+
throw 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.
| export async function exchangeGoogleCodeForUserInfo(code: string) { | |
| try { | |
| const response = await axios.post(`${SERVER_BASE_URL}/api/auth/google`, { code }); | |
| return response.data; | |
| } catch (error) { | |
| console.error("Google Token Exchange Error:", error); | |
| throw error; | |
| } | |
| } | |
| export async function exchangeGoogleCodeForUserInfo(code: string) { | |
| try { | |
| const response = await axios.post(`${SERVER_BASE_URL}/api/auth/google`, { code }); | |
| if (response.status !== 200) { | |
| throw new Error(`서버 응답 오류: ${response.status}`); | |
| } | |
| return response.data; | |
| } catch (error) { | |
| console.error("Google Token Exchange Error:", error); | |
| if (axios.isAxiosError(error)) { | |
| if (error.response?.status === 401) { | |
| throw new Error("인증에 실패했습니다."); | |
| } else if (error.response?.status === 500) { | |
| throw new Error("서버 오류가 발생했습니다."); | |
| } | |
| } | |
| throw error; | |
| } | |
| } |
🤖 Prompt for AI Agents
In features/auth/api/googleAuth.ts around lines 59 to 67, the current error
handling for the backend API call does not differentiate based on HTTP status
codes. Improve error handling by checking the HTTP status code in the catch
block and handle different cases accordingly, such as logging specific messages
or throwing custom errors for different status codes to provide clearer feedback
on the failure reason.
| const NAVER_CLIENT_ID = process.env.EXPO_PUBLIC_NAVER_CLIENT_ID; | ||
| const NAVER_CLIENT_SECRET = process.env.EXPO_PUBLIC_NAVER_CLIENT_SECRET; | ||
| const NAVER_REDIRECT_URI = process.env.EXPO_PUBLIC_NAVER_REDIRECT_URI; |
There was a problem hiding this comment.
🛠️ Refactor suggestion
환경변수 검증 및 타입 안전성 개선 필요
환경변수들이 undefined일 수 있지만 검증하지 않고 있으며, 이후 non-null assertion을 사용하고 있습니다.
const NAVER_CLIENT_ID = process.env.EXPO_PUBLIC_NAVER_CLIENT_ID;
const NAVER_CLIENT_SECRET = process.env.EXPO_PUBLIC_NAVER_CLIENT_SECRET;
const NAVER_REDIRECT_URI = process.env.EXPO_PUBLIC_NAVER_REDIRECT_URI;
+// 환경변수 검증
+if (!NAVER_CLIENT_ID || !NAVER_CLIENT_SECRET || !NAVER_REDIRECT_URI) {
+ throw new 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.
| const NAVER_CLIENT_ID = process.env.EXPO_PUBLIC_NAVER_CLIENT_ID; | |
| const NAVER_CLIENT_SECRET = process.env.EXPO_PUBLIC_NAVER_CLIENT_SECRET; | |
| const NAVER_REDIRECT_URI = process.env.EXPO_PUBLIC_NAVER_REDIRECT_URI; | |
| const NAVER_CLIENT_ID = process.env.EXPO_PUBLIC_NAVER_CLIENT_ID; | |
| const NAVER_CLIENT_SECRET = process.env.EXPO_PUBLIC_NAVER_CLIENT_SECRET; | |
| const NAVER_REDIRECT_URI = process.env.EXPO_PUBLIC_NAVER_REDIRECT_URI; | |
| // 환경변수 검증 | |
| if (!NAVER_CLIENT_ID || !NAVER_CLIENT_SECRET || !NAVER_REDIRECT_URI) { | |
| throw new Error("네이버 로그인에 필요한 환경변수가 설정되지 않았습니다."); | |
| } |
🤖 Prompt for AI Agents
In features/auth/ui/NaverLoginWebView.tsx around lines 9 to 11, the environment
variables NAVER_CLIENT_ID, NAVER_CLIENT_SECRET, and NAVER_REDIRECT_URI are
assigned without validation and later used with non-null assertions, risking
runtime errors if they are undefined. Add explicit checks to verify these
variables are defined before use, and handle the case where they are missing by
throwing an error or providing fallback logic. This ensures type safety and
prevents runtime crashes due to undefined environment variables.
| interface NaverLoginWebViewProps { | ||
| onLoginSuccess: (userInfo: any) => void; | ||
| onLoginError: (error: any) => void; | ||
| onClose: () => void; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
타입 안전성 개선 필요
props의 타입 정의에서 any 타입을 사용하고 있어 타입 안전성이 부족합니다.
+interface NaverUserInfo {
+ id: string;
+ email: string;
+ name: string;
+ nickname: string;
+ profileImage: string;
+ accessToken: string;
+}
interface NaverLoginWebViewProps {
- onLoginSuccess: (userInfo: any) => void;
- onLoginError: (error: any) => void;
+ onLoginSuccess: (userInfo: NaverUserInfo) => void;
+ onLoginError: (error: Error) => void;
onClose: () => void;
}📝 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.
| interface NaverLoginWebViewProps { | |
| onLoginSuccess: (userInfo: any) => void; | |
| onLoginError: (error: any) => void; | |
| onClose: () => void; | |
| } | |
| interface NaverUserInfo { | |
| id: string; | |
| email: string; | |
| name: string; | |
| nickname: string; | |
| profileImage: string; | |
| accessToken: string; | |
| } | |
| interface NaverLoginWebViewProps { | |
| onLoginSuccess: (userInfo: NaverUserInfo) => void; | |
| onLoginError: (error: Error) => void; | |
| onClose: () => void; | |
| } |
🤖 Prompt for AI Agents
In features/auth/ui/NaverLoginWebView.tsx around lines 13 to 17, the props
interface uses 'any' types for onLoginSuccess and onLoginError parameters, which
reduces type safety. Replace 'any' with more specific types that accurately
represent the expected userInfo and error objects to improve type safety and
catch potential issues at compile time.
| const [isChangeNavigate, setIsChangeNavigate] = useState(true); | ||
|
|
||
| // CSRF 방지를 위한 state 값 생성 (랜덤 문자열) | ||
| const STATE = Math.random().toString(36).substring(2, 15); |
There was a problem hiding this comment.
보안 취약점: 약한 STATE 생성
CSRF 보호를 위한 STATE 값이 Math.random()으로 생성되어 보안상 취약합니다.
+import { randomBytes } from 'expo-crypto';
// CSRF 방지를 위한 state 값 생성 (랜덤 문자열)
-const STATE = Math.random().toString(36).substring(2, 15);
+const STATE = randomBytes(16).toString('hex');또는 crypto가 없는 환경에서는:
-const STATE = Math.random().toString(36).substring(2, 15);
+const STATE = Date.now().toString(36) + Math.random().toString(36).substring(2);📝 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 STATE = Math.random().toString(36).substring(2, 15); | |
| import { randomBytes } from 'expo-crypto'; | |
| // CSRF 방지를 위한 state 값 생성 (랜덤 문자열) | |
| const STATE = randomBytes(16).toString('hex'); |
🤖 Prompt for AI Agents
In features/auth/ui/NaverLoginWebView.tsx at line 28, the STATE value for CSRF
protection is generated using Math.random(), which is insecure. Replace this
with a cryptographically secure random string generator, such as using the Web
Crypto API's crypto.getRandomValues() method, to create a strong, unpredictable
STATE value for better security.
| }, | ||
| data: new URLSearchParams({ | ||
| grant_type: "authorization_code", | ||
| client_id: NAVER_CLIENT_ID!, |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Non-null assertion 제거 필요
환경변수가 검증되지 않은 상태에서 non-null assertion을 사용하고 있습니다.
환경변수 검증을 추가한 후:
client_id: NAVER_CLIENT_ID!,
client_secret: NAVER_CLIENT_SECRET!,이를 다음과 같이 변경:
client_id: NAVER_CLIENT_ID,
client_secret: NAVER_CLIENT_SECRET,Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In features/auth/ui/NaverLoginWebView.tsx at line 44, remove the non-null
assertion operator (!) from NAVER_CLIENT_ID to avoid assuming the environment
variable is always defined. Instead, add validation logic before this line to
check if NAVER_CLIENT_ID is present and handle the case when it is missing, such
as throwing an error or providing a fallback, ensuring the code safely uses the
environment variable.
#8
Summary by CodeRabbit
신규 기능
버그 수정
스타일
환경설정
기타
expo-web-browser)가 추가되었습니다.