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"
로컬 테스트 사용자가 운영에선 일반 사용자로 되어 있을 수 있다. 테스트할 때 이 점을 고려해야 한다.
한 가지씩 확인하는 체크리스트
권한 문제가 나면 다음 순서대로 확인한다:
- 토큰이 유효한가? (만료 날짜 확인)
- 토큰에 필요한 권한이 있는가? (scope 확인)
- 요청하는 리소스가 자신의 것인가?
- API 엔드포인트의 권한 요구사항이 뭔가? (문서 확인)
- 로컬과 운영의 설정이 같은가?
각 단계를 통과해야 다음으로 넘어간다. 하나라도 실패하면 거기가 원인이다.
문제 해결 후 기록
권한 에러를 해결했다면 왜 그런 일이 일어났는지 기록해둔다.
- 원인: 특정 롤(예: viewer)에는 DELETE 권한이 없음
- 해결: 그 롤에 필요한 권한 추가
- 검증: 같은 롤의 다른 사용자로도 테스트해서 일관성 확인