-
Notifications
You must be signed in to change notification settings - Fork 3
[Feature/#280] 네이버, 구글 로그인 연동 및 로그인 모달 설정 #284
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
4f7c887
c10aef2
1a41612
1ccec5d
e6266f2
fe616bc
c3a801f
1f423bf
befa116
2785f7a
cefc34d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,11 +2,15 @@ import { useEffect, useRef } from "react"; | |
| import useGetSignIn from "apis/hooks/users/useGetSignIn"; | ||
| import { LoadingSpinnerIcon } from "@assets/svgs"; | ||
| import { container, iconStyle } from "./Callback.style"; | ||
| import { useNavigate, useParams } from "react-router-dom"; | ||
| import routes from "@constants/routes"; | ||
|
|
||
| const Callback: React.FC = () => { | ||
| const navigate = useNavigate(); | ||
| const { loginType } = useParams(); | ||
| const isCodeProcessed = useRef(false); | ||
| const code = new URL(window.location.href).searchParams.get("code"); | ||
| const { mutate } = useGetSignIn(); | ||
| const { mutate } = useGetSignIn(loginType); | ||
|
Comment on lines
+10
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: fd "Callback\.tsx" --type fRepository: STACKPOT/STACKPOT-FE Length of output: 95 🏁 Script executed: cat -n src/pages/Callback/Callback.tsxRepository: STACKPOT/STACKPOT-FE Length of output: 1019 🏁 Script executed: fd "useGetSignIn" --type fRepository: STACKPOT/STACKPOT-FE Length of output: 100 🏁 Script executed: cat -n src/apis/hooks/users/useGetSignIn.tsRepository: STACKPOT/STACKPOT-FE Length of output: 1344 🏁 Script executed: rg "Callback" --type tsx --type ts -B 2 -A 2 | head -50Repository: STACKPOT/STACKPOT-FE Length of output: 91 🏁 Script executed: rg "Callback" -B 2 -A 2 | head -50Repository: STACKPOT/STACKPOT-FE Length of output: 1746 🏁 Script executed: cat -n src/routes/router.tsx | grep -A 5 -B 5 "callback"Repository: STACKPOT/STACKPOT-FE Length of output: 454 🏁 Script executed: rg "callback" -i src/constants/routesRepository: STACKPOT/STACKPOT-FE Length of output: 124 🏁 Script executed: fd "routes" -type f | grep -i constRepository: STACKPOT/STACKPOT-FE Length of output: 234 🏁 Script executed: fd "routes" --type file | grep -i constRepository: STACKPOT/STACKPOT-FE Length of output: 87 🏁 Script executed: cat -n src/constants/routes.tsRepository: STACKPOT/STACKPOT-FE Length of output: 1066 🏁 Script executed: rg "useParams" src/pages/Callback/Callback.tsx -A 3 -B 3Repository: STACKPOT/STACKPOT-FE Length of output: 506 🏁 Script executed: rg "navigate.*callback\|href.*callback\|to.*callback" -iRepository: STACKPOT/STACKPOT-FE Length of output: 46 🏁 Script executed: rg "callback" -i | grep -E "href|to=|navigate|link" | head -20Repository: STACKPOT/STACKPOT-FE Length of output: 46 🏁 Script executed: rg "routes\.callback|/callback" -B 3 -A 3Repository: STACKPOT/STACKPOT-FE Length of output: 1046 🏁 Script executed: rg "google|kakao|naver" -i src/pages/Callback/ src/apis/hooks/users/Repository: STACKPOT/STACKPOT-FE Length of output: 522 loginType 유효성 검증 필수 URL 파라미터로 받은 사용자가 구글 로그인을 시도했으나 🛡️ loginType 검증 로직 제안 const Callback: React.FC = () => {
const { loginType } = useParams();
const isCodeProcessed = useRef(false);
const code = new URL(window.location.href).searchParams.get("code");
+
+ // loginType 유효성 검증
+ useEffect(() => {
+ if (!loginType || !["google", "kakao", "naver"].includes(loginType)) {
+ console.error("Invalid login type:", loginType);
+ navigate(routes.home);
+ }
+ }, [loginType, navigate]);
+
const { mutate } = useGetSignIn(loginType);
🤖 Prompt for AI Agents |
||
|
|
||
| useEffect(() => { | ||
| if (code && !isCodeProcessed.current) { | ||
|
|
@@ -15,6 +19,13 @@ const Callback: React.FC = () => { | |
| } | ||
| }, [code, mutate]); | ||
|
|
||
| useEffect(() => { | ||
| if (!loginType || !["google", "kakao", "naver"].includes(loginType)) { | ||
| console.error("Invalid loginType:", loginType); | ||
| navigate(routes.home); | ||
| } | ||
| }, [loginType]); | ||
|
|
||
| return ( | ||
| <main css={container}> | ||
| <LoadingSpinnerIcon css={iconStyle} /> | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OAuth URL은
URLSearchParams로 구성하고redirect_uri/scope/state를 보장하세요.현재 문자열 템플릿 방식은
redirect_uri/scope인코딩 누락으로 로컬/배포 환경별로 깨지기 쉽고, (특히 Naver는)state누락 시 동작 실패 또는 CSRF 방어 공백이 생길 수 있습니다.URLSearchParams+state(생성 후 sessionStorage 등에 저장, 콜백에서 검증)로 통일하는 편이 안전합니다.제안 diff (개념 예시)
const LoginModal: React.FC<LoginModalProps> = ({ onCancel }) => { - const googleLoginLink = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${ - import.meta.env.VITE_REST_GOOGLE_API_KEY - }&redirect_uri=${ - import.meta.env.VITE_GOOGLE_REDIRECT_URI - }&response_type=code&scope=email`; + const oauthState = crypto.randomUUID(); + sessionStorage.setItem("oauth_state", oauthState); + + const googleLoginLink = `https://accounts.google.com/o/oauth2/v2/auth?${new URLSearchParams({ + client_id: import.meta.env.VITE_REST_GOOGLE_API_KEY, // (명칭은 client_id인지 확인) + redirect_uri: import.meta.env.VITE_GOOGLE_REDIRECT_URI, + response_type: "code", + scope: "openid email", // 서버 요구 스코프에 맞게 조정 + state: oauthState, + }).toString()}`; const kakaoLoginLink = `https://kauth.kakao.com/oauth/authorize?client_id=${ import.meta.env.VITE_REST_API_KEY }&redirect_uri=${import.meta.env.VITE_REDIRECT_URI}&response_type=code &scope=account_email &prompt=login`; - const naverLoginLink = `https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=${ - import.meta.env.VITE_REST_NAVER_API_KEY - }&redirect_uri=${import.meta.env.VITE_NAVER_REDIRECT_URI}`; + const naverLoginLink = `https://nid.naver.com/oauth2.0/authorize?${new URLSearchParams({ + response_type: "code", + client_id: import.meta.env.VITE_REST_NAVER_API_KEY, + redirect_uri: import.meta.env.VITE_NAVER_REDIRECT_URI, + state: oauthState, + }).toString()}`;📝 Committable suggestion
🤖 Prompt for AI Agents