Careeroza
Real World Example
Where You See This
- Razorpay, Stripe, Google Cloud APIs: every API call carries a bearer token that the API validates.
- Banks (open banking / account aggregators): APIs accept tokens only with a specific audience and scope.
- Large Indian e-commerce backends run hundreds of services; each one is a resource server trusting one central identity provider.
ShopEase order-service
Customers may only see their own orders, sellers see orders for their products, and admins see everything. The token supplies identity; the service enforces ownership:
@Service
public class OrderService {
private final OrderRepository orders;
public OrderService(OrderRepository orders) { this.orders = orders; }
@PreAuthorize("hasAuthority('SCOPE_orders.read')")
public List<OrderDto> findByCustomer(String customerId) {
return orders.findByCustomerIdOrderByPlacedAtDesc(customerId).stream().map(OrderDto::from).toList();
}
// Ownership check: the order must belong to the caller, unless the caller is an admin
@PostAuthorize("returnObject.customerId() == authentication.token.subject or hasRole('ADMIN')")
public OrderDto findById(Long id) {
return orders.findById(id).map(OrderDto::from)
.orElseThrow(() -> new OrderNotFoundException(id));
}
@PreAuthorize("hasRole('SELLER')")
public List<OrderDto> ordersForSeller(String sellerId) { // controller passes jwt.getSubject()
return orders.findBySellerId(sellerId).stream().map(OrderDto::from).toList();
}
}IDOR attempt blocked
Asha tries to read Ravi's order 1077:
curl -i http://localhost:8081/api/orders/1077 -H "Authorization: Bearer $ASHA_TOKEN"Example output
HTTP/1.1 403
Content-Type: application/json
{"type":"about:blank","title":"Forbidden","status":403,"detail":"Access Denied","instance":"/api/orders/1077"}Tip: authentication.token.subject works because the principal is a JwtAuthenticationToken. Ownership checks like this stop IDOR (insecure direct object reference), which is the #1 risk in the OWASP Top 10 (Broken Access Control).