Careeroza
Ownership Checks
Roles are Not Enough
Every customer has the customer role, so a roles guard cannot stop Asha from reading Ravi's order GET /orders/ORD-9. This bug is called IDOR (Insecure Direct Object Reference) and is one of the most common API vulnerabilities. Always scope queries to the current user.
src/orders/orders.service.ts
@Injectable()
export class OrdersService {
constructor(private readonly prisma: PrismaService) {}
async findOneForUser(orderId: string, user: JwtUser) {
const order = await this.prisma.order.findFirst({
where: {
id: orderId,
...(user.roles.includes('admin') ? {} : { userId: user.id }), // owner filter in the query
},
include: { items: true },
});
// 404, not 403: do not reveal that the order exists
if (!order) throw new NotFoundException('Order not found');
return order;
}
}Example
curl -H "Authorization: Bearer <asha-token>" http://localhost:3000/orders/ORD-7781
curl -i -H "Authorization: Bearer <asha-token>" http://localhost:3000/orders/ORD-9Example output
{"id":"ORD-7781","userId":12,"status":"DELIVERED","total":"2598.00","items":[...]}
HTTP/1.1 404 Not Found
{"message":"Order not found","error":"Not Found","statusCode":404}