← 전체 글로 돌아가기

API

권한 때문에 API 요청이 막혔을 때

특정 사용자는 API를 호출할 수 없을 때는, 토큰 권한과 리소스 소유권을 함께 확인해야 한다.

권한 문제는 애매하다. 같은 요청인데도 누군가는 성공하고 누군가는 실패할 수 있다. 이럴 땐 차근차근 확인해야 한다.

먼저 인증 상태 확인하기

권한 문제는 인증 문제와 다르다. 인증은 "당신이 누구인가", 권한은 "당신이 뭘 할 수 있는가"다.

# 유효한 토큰으로 요청
curl -H "Authorization: Bearer $TOKEN" 'https://api.example.com/users/123'

# 토큰이 없으면
curl 'https://api.example.com/users/123'
# 401 Unauthorized

# 토큰은 있는데 권한이 없으면
curl -H "Authorization: Bearer $LIMITED_TOKEN" 'https://api.example.com/admin/settings'
# 403 Forbidden

401과 403의 차이가 중요하다. 401이면 토큰 자체를 확인해야 하고, 403이면 이 토큰의 권한 수준을 확인해야 한다.

토큰의 권한 레벨 확인하기

토큰마다 권한이 다르다. 일반 사용자는 자기 프로필만 볼 수 있지만, 관리자는 모든 사용자를 볼 수 있다.

# 토큰을 디코드해서 권한 확인 (JWT인 경우)
echo $TOKEN | cut -d'.' -f2 | base64 -d | jq '.scope'
# output: ["user:read", "user:write"]

# 필요한 권한
# DELETE /users/123 -> 필요: "admin:write"

토큰의 권한과 요청에 필요한 권한이 안 맞으면 403이 나온다.

리소스 소유권 확인하기

때론 권한은 맞는데도 요청이 실패할 수 있다. 자기 리소스가 아닌 다른 사람의 리소스를 건드리려고 할 때다.

# 자기 프로필 조회 (성공)
curl -H "Authorization: Bearer $TOKEN" 'https://api.example.com/users/self'

# 다른 사용자 프로필 조회 (실패할 수 있음)
curl -H "Authorization: Bearer $TOKEN" 'https://api.example.com/users/someone_else_id'

API 에러 메시지에 "You don't have permission"이라고 나오면, 이 사용자가 이 리소스에 접근할 권한이 없다는 뜻이다.

로컬과 운영 환경 비교하기

로컬에선 모든 사용자에게 관리자 권한을 줄 수도 있다. 그래서 로컬에선 잘되는데 운영에선 실패할 수 있다.

# 로컬 환경의 사용자 권한
sqlite3 db.sqlite3 "SELECT id, email, is_admin FROM users LIMIT 5"

# 운영 환경의 사용자 권한
kubectl exec postgresql -- psql -U admin -d mydb -c "SELECT id, email, is_admin FROM users LIMIT 5"

로컬 테스트 사용자가 운영에선 일반 사용자로 되어 있을 수 있다. 테스트할 때 이 점을 고려해야 한다.

한 가지씩 확인하는 체크리스트

권한 문제가 나면 다음 순서대로 확인한다:

  1. 토큰이 유효한가? (만료 날짜 확인)
  2. 토큰에 필요한 권한이 있는가? (scope 확인)
  3. 요청하는 리소스가 자신의 것인가?
  4. API 엔드포인트의 권한 요구사항이 뭔가? (문서 확인)
  5. 로컬과 운영의 설정이 같은가?

각 단계를 통과해야 다음으로 넘어간다. 하나라도 실패하면 거기가 원인이다.

문제 해결 후 기록

권한 에러를 해결했다면 왜 그런 일이 일어났는지 기록해둔다.

  • 원인: 특정 롤(예: viewer)에는 DELETE 권한이 없음
  • 해결: 그 롤에 필요한 권한 추가
  • 검증: 같은 롤의 다른 사용자로도 테스트해서 일관성 확인