sapui5tutors SAPUI5 • Fiori • SAP BTP Step-by-step tutorials Real project examples Interview Q&A
Practical SAPUI5 • Fiori • SAP BTP tutorials and interview prep

CAPM Authorization: @requires and @restrict Deep-Dive

Two annotations, full access control

CAP's authorization model is declarative: @requires guards whole services, @restrict guards entities with row-level rules. Together they cover nearly every real-world requirement without custom code.

@requires = who may enter the service. @restrict = who may do what, to which rows.


@requires: service-level gates

@requires : 'authenticated-user'
service CatalogService {
  entity Books as projection on my.Books;
};

@requires : 'admin'
service AdminService {
  entity Orders as projection on my.Orders;
};

The first service needs any logged-in user; the second needs the admin scope from your XSUAA setup. Unauthorized requests get a clean 403.


@restrict: fine-grained entity rules

service OrderService {
  @(restrict: [
    { grant: 'READ',  to: 'viewer' },
    { grant: ['READ','WRITE'], to: 'sales' },
    { grant: '*', to: 'admin' }
  ])
  entity Orders as projection on my.Orders;
}

Viewers read, salespeople read and write, admins do everything. Grants map to OData operations — CAP translates them into CUD restrictions automatically.


Row-level security with where conditions

This is where @restrict earns its reputation:

@(restrict: [
  { grant: 'READ',
    to: 'sales',
    where: 'region = $user.region' }
])
entity Orders as projection on my.Orders;

Each salesperson sees only their region's orders. $user exposes JWT attributes — map IdP attributes (department, region, cost center) into the token via XSUAA configuration, then filter on them.

Row-level rules apply at the database query level, not in application code. They can't be bypassed by clever OData queries.


Instance-based vs static

  • Static (to: 'role') — same rule for all rows. Fast, simple, covers most cases.
  • Dynamic (where: 'owner = $user.id') — per-row evaluation. "Users see their own records."
  • Combine — multiple restrict entries are OR'd; a user matching any entry gets that grant.
  • Test as different users — authorization bugs are silent; verify with viewer, sales, and admin identities.

Testing authorization properly

Authorization bugs are silent — the app works for you (admin) and fails for everyone else. Test with at least three identities: an admin, a restricted role, and an unauthenticated request.

For automated tests, CAP supports mock users with specific roles. Assert the matrix explicitly: viewer gets 200 on READ and 403 on CREATE; sales gets 200 on both; anonymous gets 401 everywhere.

Row-level rules need data-level tests: create records for two regions, log in as each region's user, and verify neither sees the other's rows. Query-level enforcement means this either works or it doesn't — there's no middle ground to debug.


Declare it, don't code it

Resist the urge to hand-roll authorization in handlers. Annotations are visible, auditable, and enforced consistently — including for actions and functions.

Hit a tricky authorization scenario? Describe it in the comments.