Đặt ở business logic phía sau resolver, nơi biết cả người dùng lẫn record cụ thể.
Kiểm tra chỉ ở gateway là chưa đủ vì nó chỉ biết người dùng là ai, không biết họ có quyền xem đúng record đang yêu cầu hay không.
// authorize per field, not per route — one query can touch many types
const resolvers = {
Post: {
revenue: (post, _a, ctx) => (ctx.can('read:revenue', post) ? post.revenue : null),
},
}Đặc thù làm việc này khó hơn REST: cùng một kiểu dữ liệu được với tới từ nhiều đường trong đồ thị. Một bài viết có thể được truy cập trực tiếp, qua tác giả, qua danh sách bình luận, hoặc qua kết quả tìm kiếm. Nếu kiểm tra quyền chỉ nằm ở một đường thì các đường khác bị hở.
Các mức phân quyền: theo thao tác, theo kiểu, theo field, và theo từng record. Mức theo record khó nhất và hay bị bỏ sót nhất.
Lưu ý hiệu năng: kiểm tra quyền theo từng record trong danh sách dài dễ tạo ra chính vấn đề N+1 — nên tải dữ liệu phân quyền theo lô hoặc đẩy điều kiện xuống truy vấn database.