CDS Views
Architect / Cross-trackadvanced

CDS Views Part 8: DCL Access Control

Key takeaway

Protect CDS data with Data Control Language (DCL): access control roles that link CDS fields to PFCG authorization objects, the authorizationCheck annotation values, how ABAP SELECTs are filtered automatically, inheritance between views, and how to test and troubleshoot missing rows.

Explanation

📌 KEY POINTS
✅ DCL (Data Control Language) defines row-level authorizations for CDS views in a separate object: define role … grant select on … where …

✅ aspect pfcg_auth links CDS fields to a PFCG authorization object (e.g. V_VBAK_VKO for sales area); the user sees only rows their roles allow.

✅ Every SELECT on the CDS entity — from ABAP, OData or analytics — is filtered automatically; no AUTHORITY-CHECK code needed for those rows.

⚠️ DCL filters silently: users without authorization get fewer rows, not an error. "Data missing" tickets are often DCL working as designed.

━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE

Part 7 made views meaningful. Now we make sure each user sees only the data they are allowed to see.

━━━━━━━━━━━━━━━━━━━━
▶ 1. authorizationCheck ANNOTATION

  • #CHECK: a DCL role should exist; syntax warning if missing.
  • #NOT_REQUIRED: no DCL expected (e.g. customizing, texts).
  • #PRIVILEGED_ONLY: only privileged access allowed.
  • #NOT_ALLOWED: DCL must not be defined.
  • The annotation does not protect anything by itself — the DCL role does.

━━━━━━━━━━━━━━━━━━━━
▶ 2. DCL ROLE SYNTAX

  • New object in ADT: Core Data Services → Access Control.
  • define role <name> { grant select on <entity> where <condition>; }
  • Conditions: literal (Country = 'DE'), user ($session.user / aspect user), or PFCG aspect.

━━━━━━━━━━━━━━━━━━━━
▶ 3. PFCG ASPECT

  • ( SalesOrganization, DistributionChannel, Division ) = aspect pfcg_auth( V_VBAK_VKO, VKORG, VTWEG, SPART, ACTVT = '03' )
  • Field list on the left maps to authorization fields on the right in the same order.
  • ACTVT = '03' = display.
  • Same PFCG roles used by VA03 now control the CDS data.

━━━━━━━━━━━━━━━━━━━━
▶ 4. INHERITANCE

  • Each CDS entity needs its own role — a consumption view does not automatically inherit protection from the view below.
  • Use grant select on ZC_X where inheriting conditions from entity ZI_X to reuse rules.
  • SAP standard I_ views usually ship with their DCL roles.

━━━━━━━━━━━━━━━━━━━━
▶ 5. ABAP CONSUMERS

  • Classic SELECT from the CDS name: DCL applied automatically.
  • SELECT from underlying tables or a classic view's SQL view name: no DCL — a common security gap.
  • Background jobs or interfaces that must see everything: privileged access (modern ABAP SQL WITH PRIVILEGED ACCESS) — use sparingly and document.

━━━━━━━━━━━━━━━━━━━━
▶ 6. TESTING AND TROUBLESHOOTING

  • Compare row counts for a restricted test user vs. an unrestricted user.
  • Check the user's PFCG values for the authorization object.
  • In ADT, open the view and check the access control objects assigned to it.
  • Remember: missing authorization = fewer rows, no message.

━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP

  1. Create ZI_SalesOrderAuth with SalesOrganization, DistributionChannel, Division; set authorizationCheck #CHECK.
  2. Create DCL role ZI_SalesOrderAuth with pfcg_auth on V_VBAK_VKO.
  3. Protect ZC_SalesOrderAuthList with inheriting conditions.
  4. Run a classic report as two users with different sales org authorization and compare counts.

✅ CHECKPOINT: you can secure a CDS view with DCL and explain why a user sees fewer rows.

Code example

ABAP Code
// ===== STEP 1: view to protect =====@AccessControl.authorizationCheck: #CHECK@EndUserText.label: 'Sales orders - authorization protected'define view entity ZI_SalesOrderAuth  as select from vbak{  key vbeln as SalesOrder,      vkorg as SalesOrganization,      vtweg as DistributionChannel,      spart as Division,      kunnr as SoldToParty,      @Semantics.amount.currencyCode: 'TransactionCurrency'      netwr as NetAmount,      waerk as TransactionCurrency} // ===== STEP 2: DCL role (ADT: New > Access Control) =====@EndUserText.label: 'Access control for ZI_SalesOrderAuth'@MappingRole: truedefine role ZI_SalesOrderAuth {  grant select on ZI_SalesOrderAuth    where ( SalesOrganization, DistributionChannel, Division ) =          aspect pfcg_auth( V_VBAK_VKO, VKORG, VTWEG, SPART, ACTVT = '03' );} // ===== STEP 3: consumption view + inherited rule =====@AccessControl.authorizationCheck: #CHECK@EndUserText.label: 'Sales order list - protected'define view entity ZC_SalesOrderAuthList  as select from ZI_SalesOrderAuth{  key SalesOrder,      SalesOrganization,      DistributionChannel,      Division,      SoldToParty,      @Semantics.amount.currencyCode: 'TransactionCurrency'      NetAmount,      TransactionCurrency} @EndUserText.label: 'Access control for ZC_SalesOrderAuthList'@MappingRole: truedefine role ZC_SalesOrderAuthList {  grant select on ZC_SalesOrderAuthList    where inheriting conditions from entity ZI_SalesOrderAuth;} * ===== STEP 4: classic report - DCL applied automatically =====REPORT zcds_dcl_test. DATA: lv_cds   TYPE i,      lv_table TYPE i. START-OF-SELECTION.  SELECT COUNT(*) FROM zc_salesorderauthlist INTO lv_cds.   "filtered by DCL  SELECT COUNT(*) FROM vbak INTO lv_table.                  "NOT filtered   WRITE: / 'Rows visible via CDS  :', lv_cds,         / 'Rows in table VBAK    :', lv_table,         / 'User:', sy-uname.* Lower CDS count = DCL working. Never bypass by reading VBAK in apps.

Real project scenario

After go-live in 8 markets, the Brazil sales team saw German orders in a custom Fiori list. The CDS view had @AccessControl.authorizationCheck: #CHECK but nobody had created the DCL role — the annotation alone protects nothing.
The team added a DCL role mapping sales area to V_VBAK_VKO, added inheriting roles for all consumption views, and a code-review rule: #CHECK without a role fails review. A week later a support ticket "missing orders" turned out to be a user lacking one division in PFCG — DCL working correctly.

Common mistakes

  • Setting #CHECK but never creating the DCL role.
  • Assuming a consumption view inherits protection automatically.
  • Reading base tables or SQL view names in apps, bypassing DCL.
  • Mismatched field order between the CDS field list and the pfcg_auth fields.
  • Treating missing rows as a bug without checking the user's authorizations.

Best practices

  • Use #CHECK plus a DCL role for all business data views.
  • Reuse existing PFCG objects so one role concept covers GUI and CDS.
  • Use inheriting conditions for view stacks.
  • Allow privileged access only for documented technical cases.
  • Test with restricted users before go-live.

Interview angle

Questions: "How do you secure CDS views?", "What does aspect pfcg_auth do?", "Why does a user see fewer rows than expected?"
Strong answer: DCL roles (define role, grant select … where) define row-level rules; pfcg_auth maps CDS fields to a PFCG object like V_VBAK_VKO with ACTVT 03; applied automatically for every SELECT on the entity. The annotation alone does not protect; each view needs a role or inheritance. DCL filters silently, so fewer rows usually means missing PFCG values; reading base tables bypasses DCL.

Practice this lesson

Quick check

1. Which object restricts CDS rows according to a user's PFCG authorizations?

2. A CDS view has @AccessControl.authorizationCheck: #CHECK but no DCL role exists. What do users see?

3. Row-level authorisation is via:

Interview questions

1. What is DCL?

Answer it in your own words first, then compare.

2. After go-live, a Brazil user sees German sales orders in a custom Fiori app. The CDS view has @AccessControl.authorizationCheck: #CHECK. What happened and how do you fix it?

Answer it in your own words first, then compare.

Practice more with Interview AI →

Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.

More lessons in this topic

Interview questions on this topic

Related SAP topics