3. 권한은 서버에서 끝난다
사고 시나리오
섹션 제목: “사고 시나리오”관리자 전용 기능이라 일반 사용자에게는 버튼을 숨겼다. 막았다고 생각했다. 하지만 사용자는 개발자 도구를 열고 서버 API를 직접 호출할 수 있다. 서버가 검사하지 않으면, 화면에 없는 기능도 실행된다. 삭제도, 정산도, 다른 사람 데이터 조회도.
프론트엔드의 권한 처리는 UX다. 보안은 서버가 요청마다 검사할 때만 존재한다. 클라이언트가 보내는 모든 것(역할 값, 사용자 ID, 히든 필드)은 조작 가능한 입력으로 취급한다.
실무 처방
섹션 제목: “실무 처방”- 권한 검사를 미들웨어나 요청 훅 한 곳에 모아 모든 요청이 통과하게 한다. 핸들러마다 따로 검사하면 하나는 반드시 빠뜨린다.
- 기본값은 거부(fail-closed)로. 역할이 등록 안 된 사용자, 인증 헤더가 없는 요청은 최소 권한 또는 차단이다.
- 신뢰할 수 있는 신원은 서버가 검증한 것(세션, 검증된 토큰, 인증 프록시가 주입한 헤더)뿐이다. 클라이언트가 보낸 role 파라미터를 믿지 않는다.
- 수평 권한도 검사한다 — 로그인했다고 끝이 아니라, “이 사용자가 이 리소스의 소유자인가”를 리소스 단위로 확인한다.
- 테스트에 “권한 없는 사용자가 호출하면 403”을 명시적으로 넣는다.
체크리스트
섹션 제목: “체크리스트”- 모든 쓰기 API가 서버 측 권한 검사를 통과한다 (버튼 숨김에 의존하지 않음)
- 미등록·미인증 사용자의 기본값이 거부다 (fail-closed)
- 다른 사용자의 리소스 ID를 넣어 호출하면 거부된다
- 권한 없는 호출이 403이 되는 테스트가 있다