Skip to content

fix(web): mentor auth gating by API response#516

Merged
manNomi merged 2 commits intomainfrom
fix/mentor-api-auth-gating-pr
May 6, 2026
Merged

fix(web): mentor auth gating by API response#516
manNomi merged 2 commits intomainfrom
fix/mentor-api-auth-gating-pr

Conversation

@manNomi
Copy link
Copy Markdown
Contributor

@manNomi manNomi commented May 4, 2026

요약

  • 멘토 페이지 진입 시 인가/역할 분기를 클라이언트 토큰 파싱 기반에서 API 응답 기반으로 전환했습니다.
  • 멘토 페이지 무한 스피너 이슈를 방지하도록 인증 실패 경로를 정리했습니다.
  • 관련 선행 변경(멘토 페이지 lazy 제거, middleware 사전 인가 제거)도 함께 포함됩니다.

포함 커밋

  1. cbaa2c8a - 멘토 페이지 lazy loading 제거
  2. 85330883 - middleware 사전 인가 및 연관 dead flow 제거
  3. 052d86a9 - 멘토 페이지 인가를 useGetMyInfo().role 기반으로 전환

주요 변경 사항

  • apps/web/src/app/mentor/_ui/MentorClient/index.tsx
    • postReissueToken/토큰 상태 기반 수동 분기 제거
    • useGetMyInfo 응답의 role로 멘토/멘티 렌더 분기
    • 401/403 또는 사용자 정보 없음 시 /login 리다이렉트
    • 비인증 에러는 스피너 고착 대신 재시도 UI 표시
    • ADMIN은 기존 정책대로 clientRole 토글값 우선(없으면 멘토 UI)
  • apps/web/src/middleware.ts
    • 보호 경로 사전 인가(선리다이렉트) 제거
    • stage robots/probe 차단 로직 유지
  • 문서 동기화
    • apps/web/AUTHENTICATION.md
    • docs/auth-refresh-edge-cases.md

검증

  • pnpm --filter @solid-connect/web lint:check
  • pnpm --filter @solid-connect/web typecheck
  • pre-push hook 통과 (ci:check + next build)

@manNomi manNomi requested review from enunsnv and wibaek as code owners May 4, 2026 11:55
@vercel
Copy link
Copy Markdown

vercel Bot commented May 4, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
solid-connect-web-admin Ready Ready Preview, Comment May 4, 2026 11:58am
solid-connection-web Ready Ready Preview, Comment May 4, 2026 11:58am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

Walkthrough

이 변경은 인증 흐름의 아키텍처를 서버 미들웨어 중심에서 클라이언트 인터셉터 중심으로 재설계합니다.

  1. 인증 강제 로직 제거: 미들웨어에서 로그인 리다이렉트 기능을 완전히 삭제하고, loginNeedPages 목록과 쿠키 기반 NEED_LOGIN 상태 처리를 폐기합니다.

  2. 클라이언트 기반 토큰 관리 전환: ReissueProvider와 Axios 인터셉터를 통해 앱 초기화 및 API 요청 시점에 토큰을 재발급하도록 변경하며, 401 응답 시 1회 재시도 로직을 추가합니다.

  3. 컴포넌트 단순화: LoginContent에서 "need login" 쿠키/토스트 로직을 제거하고, MentorClient에서 직접 토큰 검증 대신 useGetMyInfo() 훅 기반의 인증 상태 파악으로 변경합니다.

  4. 상태 저장소 정리: Zustand의 useAuthStore에서 isNeedLogin 플래그를 제거하여 불필요한 상태 추적을 폐기합니다.

  5. 문서 동기화: 인증 판단 경계와 토큰 상태별 동작을 클라이언트 중심 흐름으로 재서술하며, 멘토/커뮤니티 페이지에서의 인증 필요 시점을 명확히 합니다.


Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 분


Suggested reviewers

  • wibaek
  • enunsnv
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 제목은 PR의 핵심 변경사항인 멘토 페이지의 인가 방식을 API 응답 기반으로 전환하는 내용을 명확하게 요약하고 있습니다.
Description check ✅ Passed 설명이 요약, 포함 커밋, 주요 변경 사항, 검증을 포함하여 구조적으로 잘 작성되었으나, 템플릿의 필수 섹션인 '관련 이슈'와 '특이 사항'이 누락되었습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/mentor-api-auth-gating-pr

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.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added the web label May 4, 2026
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +16 to +20
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);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Revalidate auth before trusting cached myInfo role

이 분기는 useGetMyInfo()의 캐시 데이터만으로 인증/역할을 확정하기 때문에, 이전 로그인에서 채워진 프로필 캐시가 남아 있으면(해당 쿼리는 staleTime: Infinity 설정) 현재 토큰이 만료되었거나 refresh가 없는 상태에서도 /mentor 진입 시 로그인 리다이렉트 없이 멘토/멘티 화면이 바로 렌더될 수 있습니다. 기존 구현은 토큰 유효성/재발급 결과를 먼저 확인했지만, 현재 로직은 캐시된 role이 있으면 인증 검증을 우회하므로 세션 만료 후에도 보호 UI가 노출되는 회귀가 발생합니다.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 5d9ccfc and 052d86a.

📒 Files selected for processing (6)
  • apps/web/AUTHENTICATION.md
  • apps/web/src/app/login/LoginContent.tsx
  • apps/web/src/app/mentor/_ui/MentorClient/index.tsx
  • apps/web/src/lib/zustand/useAuthStore.ts
  • apps/web/src/middleware.ts
  • docs/auth-refresh-edge-cases.md
💤 Files with no reviewable changes (2)
  • apps/web/src/lib/zustand/useAuthStore.ts
  • apps/web/src/middleware.ts

Comment on lines +27 to +30
### 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`으로 이동합니다.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

Suggested change
### 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)별 접근 제어 흐름을 예시로
추가하세요.

Comment on lines +8 to 12
- 서버 진입(Next middleware): 인증 선리다이렉트 없음 (robots/probe 차단만 수행)
- 앱 초기화(`ReissueProvider`): `/auth/reissue` 1회 시도
- 클라이언트 API 요청(axios interceptor): `accessToken` 유효성 확인 + 필요 시 재발급
- 멘토 진입 페이지: 렌더 전 access 유효성 확인 후 필요 시 재발급
- 채팅 소켓 연결: access 유효성 확인 후 연결
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

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.

@manNomi manNomi merged commit 5e6e9eb into main May 6, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant