C.W.K.
Stream
Lesson 06 of 09 · published

Protected Route

~20 min · defense in depth, auth

Level 0Curious
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

Defense in depth

Auth check 한 개 의지하지 마. Layer — 각각 다른 게 놓치는 거 잡아.

Layer잡는 것
ProxyBot 과 일반 user 가 unauthenticated 로 protected URL hit
LayoutProxy 안 거치고 누군가 도착하는 server-rendered page (예: preview deploy)
Server Action / Route HandlerInternet 어디서든 programmatic POST

각 layer 의 목적

Proxy 가 redirect/UX gate. Layout 이 "이 page render 면 data leak" gate. Action/handler 가 "page render 없이도 data write 일어날 수 있음" gate. 마지막 게 security gate — skip 못 하는 유일한 거.

Code

Layer 1 — proxy·ts
// proxy.ts
export function proxy(request: NextRequest) {
  const session = request.cookies.get('session');
  if (!session && request.nextUrl.pathname.startsWith('/app')) {
    return NextResponse.redirect(new URL('/login', request.url));
  }
  return NextResponse.next();
}
Layer 2 — layout·tsx
// app/(app)/layout.tsx
import { auth } from '@/auth';
import { redirect } from 'next/navigation';

export default async function AppLayout({ children }: { children: React.ReactNode }) {
  const session = await auth();
  if (!session) redirect('/login');
  return (
    <>
      <AppNav user={session.user} />
      {children}
    </>
  );
}
Layer 3 — 모든 action 검증·ts
'use server';
import { auth } from '@/auth';

export async function deleteAccount() {
  const session = await auth();
  if (!session) throw new Error('Unauthorized');
  await db.user.delete({ where: { id: session.user.id } });
}

External links

Exercise

App 의 sensitive action 골라 (account 삭제, money transfer 등). Proxy, layout, action level 에 명시적 auth check 추가. 각 layer bypass 시도하고 가장 깊은 게 막는지 확인.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.