fix(web): mentor auth gating by API response#516
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Walkthrough이 변경은 인증 흐름의 아키텍처를 서버 미들웨어 중심에서 클라이언트 인터셉터 중심으로 재설계합니다.
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 분 Suggested reviewers
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Review rate limit: 0/1 reviews remaining, refill in 60 minutes.Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 052d86a9d6
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| const { data: myInfo, isLoading, isFetching, isError, error, refetch } = useGetMyInfo(); | ||
| const role = myInfo?.role; | ||
| const status = (error as AxiosError | null)?.response?.status; | ||
| const isUnauthorized = status === 401 || status === 403; | ||
| const isAuthResolving = isLoading || (isFetching && !role); |
There was a problem hiding this comment.
Revalidate auth before trusting cached myInfo role
이 분기는 useGetMyInfo()의 캐시 데이터만으로 인증/역할을 확정하기 때문에, 이전 로그인에서 채워진 프로필 캐시가 남아 있으면(해당 쿼리는 staleTime: Infinity 설정) 현재 토큰이 만료되었거나 refresh가 없는 상태에서도 /mentor 진입 시 로그인 리다이렉트 없이 멘토/멘티 화면이 바로 렌더될 수 있습니다. 기존 구현은 토큰 유효성/재발급 결과를 먼저 확인했지만, 현재 로직은 캐시된 role이 있으면 인증 검증을 우회하므로 세션 만료 후에도 보호 UI가 노출되는 회귀가 발생합니다.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/web/AUTHENTICATION.md`:
- Around line 27-30: 문서의 "4. Page-level Guards" 설명을 토큰 직접 검사 대신 role 기반 분기임을 명확히
하도록 바꿔주세요: 현재 멘토 페이지는 컴포넌트가 토큰을 직접 읽는 구조가 아니라 useGetMyInfo().role과 에러 상태로 분기하여
필요한 경우 /login으로 리다이렉트하므로 해당 로직(예: useGetMyInfo().role, 에러 체크, /login으로의 이동)을
명시적으로 기술하고 역할(role)별 접근 제어 흐름을 예시로 추가하세요.
In `@docs/auth-refresh-edge-cases.md`:
- Around line 8-12: The mentor-page doc is outdated: update the "멘토 진입 페이지"
description to reflect the current implementation where MentorClient
(apps/web/src/app/mentor/_ui/MentorClient/index.tsx) does NOT pre-check the
access token but instead renders based on the result/error state from
useGetMyInfo() (the /my API response); revise the sentence to state that the
page relies on useGetMyInfo() response/error to determine authentication and
trigger any reissue flows rather than performing a direct token pre-check.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
Run ID: b279b1aa-3b19-44c4-ae6c-eff28b89f5f4
📒 Files selected for processing (6)
apps/web/AUTHENTICATION.mdapps/web/src/app/login/LoginContent.tsxapps/web/src/app/mentor/_ui/MentorClient/index.tsxapps/web/src/lib/zustand/useAuthStore.tsapps/web/src/middleware.tsdocs/auth-refresh-edge-cases.md
💤 Files with no reviewable changes (2)
- apps/web/src/lib/zustand/useAuthStore.ts
- apps/web/src/middleware.ts
| ### 4. Page-level Guards | ||
|
|
||
| ```typescript | ||
| if (needLogin && !refreshToken) { | ||
| const isCommunityRoute = url.pathname === "/community" || url.pathname.startsWith("/community/"); | ||
| url.pathname = "/login"; | ||
| if (isCommunityRoute) { | ||
| url.searchParams.set("reason", "community-members-only"); | ||
| } | ||
| return NextResponse.redirect(url); | ||
| } | ||
| ``` | ||
| - 인증이 필요한 UI(예: 멘토 페이지)는 클라이언트에서 재발급/토큰 상태를 확인합니다. | ||
| - 필요한 경우 페이지 내부 로직에서 `/login`으로 이동합니다. |
There was a problem hiding this comment.
1. 페이지 가드 설명도 role 기반 분기로 적어 두는 편이 정확합니다.
지금 멘토 페이지는 토큰 상태를 컴포넌트가 직접 읽는 구조가 아니라 useGetMyInfo().role와 에러 상태로 분기합니다. 여기 표현이 그대로면 문서만 봤을 때는 여전히 “페이지가 토큰을 직접 검사한다”로 이해되기 쉬워요.
문구 예시
-- 인증이 필요한 UI(예: 멘토 페이지)는 클라이언트에서 재발급/토큰 상태를 확인합니다.
-- 필요한 경우 페이지 내부 로직에서 `/login`으로 이동합니다.
+- 인증이 필요한 UI(예: 멘토 페이지)는 관련 프로필 API 응답과 에러 상태로 접근 권한을 판단합니다.
+- 토큰 재발급과 401 재시도는 interceptor가 처리하고, 페이지는 권한 미충족 시 `/login`으로 이동합니다.📝 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.
| ### 4. Page-level Guards | |
| ```typescript | |
| if (needLogin && !refreshToken) { | |
| const isCommunityRoute = url.pathname === "/community" || url.pathname.startsWith("/community/"); | |
| url.pathname = "/login"; | |
| if (isCommunityRoute) { | |
| url.searchParams.set("reason", "community-members-only"); | |
| } | |
| return NextResponse.redirect(url); | |
| } | |
| ``` | |
| - 인증이 필요한 UI(예: 멘토 페이지)는 클라이언트에서 재발급/토큰 상태를 확인합니다. | |
| - 필요한 경우 페이지 내부 로직에서 `/login`으로 이동합니다. | |
| ### 4. Page-level Guards | |
| - 인증이 필요한 UI(예: 멘토 페이지)는 관련 프로필 API 응답과 에러 상태로 접근 권한을 판단합니다. | |
| - 토큰 재발급과 401 재시도는 interceptor가 처리하고, 페이지는 권한 미충족 시 `/login`으로 이동합니다. |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/web/AUTHENTICATION.md` around lines 27 - 30, 문서의 "4. Page-level Guards"
설명을 토큰 직접 검사 대신 role 기반 분기임을 명확히 하도록 바꿔주세요: 현재 멘토 페이지는 컴포넌트가 토큰을 직접 읽는 구조가 아니라
useGetMyInfo().role과 에러 상태로 분기하여 필요한 경우 /login으로 리다이렉트하므로 해당 로직(예:
useGetMyInfo().role, 에러 체크, /login으로의 이동)을 명시적으로 기술하고 역할(role)별 접근 제어 흐름을 예시로
추가하세요.
| - 서버 진입(Next middleware): 인증 선리다이렉트 없음 (robots/probe 차단만 수행) | ||
| - 앱 초기화(`ReissueProvider`): `/auth/reissue` 1회 시도 | ||
| - 클라이언트 API 요청(axios interceptor): `accessToken` 유효성 확인 + 필요 시 재발급 | ||
| - 멘토 진입 페이지: 렌더 전 access 유효성 확인 후 필요 시 재발급 | ||
| - 채팅 소켓 연결: access 유효성 확인 후 연결 |
There was a problem hiding this comment.
1. 멘토 페이지 설명을 지금 구현 기준으로 다시 맞춰 주세요.
현재 구현은 apps/web/src/app/mentor/_ui/MentorClient/index.tsx에서 access 토큰을 페이지가 직접 선검사하는 방식이 아니라, useGetMyInfo()의 /my 응답과 에러 상태로 분기합니다. 이 문구가 남아 있으면 QA와 운영 문서가 다시 예전 토큰-선검사 모델로 읽혀요.
문구 예시
-- 멘토 진입 페이지: 렌더 전 access 유효성 확인 후 필요 시 재발급
+- 멘토 진입 페이지: `useGetMyInfo()`의 `/my` 응답(role)과 에러 상태로 분기
+- 토큰 재발급과 401 재시도는 axios interceptor가 담당🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/auth-refresh-edge-cases.md` around lines 8 - 12, The mentor-page doc is
outdated: update the "멘토 진입 페이지" description to reflect the current
implementation where MentorClient
(apps/web/src/app/mentor/_ui/MentorClient/index.tsx) does NOT pre-check the
access token but instead renders based on the result/error state from
useGetMyInfo() (the /my API response); revise the sentence to state that the
page relies on useGetMyInfo() response/error to determine authentication and
trigger any reissue flows rather than performing a direct token pre-check.
요약
포함 커밋
cbaa2c8a- 멘토 페이지 lazy loading 제거85330883- middleware 사전 인가 및 연관 dead flow 제거052d86a9- 멘토 페이지 인가를useGetMyInfo().role기반으로 전환주요 변경 사항
apps/web/src/app/mentor/_ui/MentorClient/index.tsxpostReissueToken/토큰 상태 기반 수동 분기 제거useGetMyInfo응답의role로 멘토/멘티 렌더 분기/login리다이렉트ADMIN은 기존 정책대로clientRole토글값 우선(없으면 멘토 UI)apps/web/src/middleware.tsapps/web/AUTHENTICATION.mddocs/auth-refresh-edge-cases.md검증
pnpm --filter @solid-connect/web lint:checkpnpm --filter @solid-connect/web typecheckci:check+next build)