Appearance
Lesson 15 — Authorization: CDS DCL and RAP Authorization
Lesson 14 answered:
text
Is this operation meaningful for the current business state?For example:
text
Status = N
→ confirm can be enabled
Status = X
→ confirm can be disabledThat is:
text
feature controlLesson 15 asks a different question:
text
Is this user allowed to see or change this data?That is:
text
authorizationToday you will protect the Reservation Business Object at two levels:
text
CDS DCL
→ controls read access to rows
RAP authorization
→ controls modifying operationsThe architecture becomes:
text
Consumer
↓
CDS / EML
↓
Authorization Layer
├─ CDS DCL for reads
├─ RAP global authorization
└─ RAP instance authorization
↓
RAP Business Object
↓
PersistenceLesson information
| Teacher-led time | About 3 hours |
| Self-practice time | About 3 hours |
| Environment | SAP BTP ABAP Trial |
| Prerequisite | Lesson 14 + Checkpoint 3 |
| Business Object | ZR_RESERVATION_### |
| Behavior Pool | ZBP_R_RESV_### |
| Authorization test class | ZCL_RESV_AUTH_### |
| New business field | ResponsibleUser |
| New repository object | CDS Access Control / DCL |
| Main outcome | User-dependent read and write protection |
Replace:
text
###with your own student/group suffix.
Learning objectives
After the teacher-led part, you should be able to:
- explain the difference between feature control and authorization;
- explain the difference between read authorization and write authorization;
- explain what CDS DCL protects;
- create a CDS Access Control object in ADT;
- use
@AccessControl.authorizationCheck: #CHECK; - use
@MappingRole: true; - use
grant select on; - use the predefined DCL
aspect user; - explain why DCL is applied implicitly to protected CDS access;
- explain what RAP global authorization means;
- explain what RAP instance authorization means;
- replace
authorization master ( none )withauthorization master ( global, instance ); - generate
get_global_authorizations; - generate
get_instance_authorizations; - use
if_abap_behv=>auth-allowed; - use
if_abap_behv=>auth-unauthorized; - use
GET PERMISSIONS ONLY GLOBAL AUTHORIZATION; - use
GET PERMISSIONS ONLY INSTANCE AUTHORIZATION; - delegate action authorization to update authorization;
- prove that an action can be feature-enabled but authorization-denied;
- explain why
IN LOCAL MODEbelongs to provider-side authorization implementation; - distinguish BTP Trial training checks from productive PFCG-based authorization design.
1. Authorization is not feature control
Lesson 14 used:
text
Statusto decide whether:
text
confirm
cancel
Fee editingwere currently available.
That is business-state logic.
Authorization answers:
text
Who is the user?
What is the user allowed to do?
Which instances belong to that user?Do not merge the concepts.
2. One instance can have two different answers
Imagine:
text
Reservation Status = NFeature control may say:
text
confirm = enabledBut authorization may say:
text
current user is not responsible for this Reservation
→ confirm not authorizedBoth can be true:
text
business state allows it
user permission denies it3. Read authorization vs write authorization
For this course:
text
CDS DCL
→ protects reads
RAP authorization
→ protects modifying operationsQuestions:
text
Which rows may this user read?
May this user update/delete/execute an action?These are complementary layers.
4. Authorization model for today
Add a business field:
text
ResponsibleUserMeaning:
The technical ABAP user responsible for the Reservation.
Read rule:
text
A user may read Reservations
only when ResponsibleUser = current userWrite rule:
text
A user may update a Reservation
only when ResponsibleUser = current userActions:
text
confirm
cancelreuse:
text
update authorizationDelete remains allowed in this training lesson so cleanup stays repeatable.
5. Why not use LocalCreatedBy?
LocalCreatedBy is an administrative audit field.
Business ownership can differ from creation identity.
Example:
text
CreatedBy = USER_A
ResponsibleUser = USER_BSo ownership deserves its own business field.
6. Add responsible_user to persistence
Open:
text
ZRESV_###Add:
abap
responsible_user : abp_creation_user;Do not make it:
text
KEY
NOT NULLbecause older Lesson 12–14 rows may already exist.
Activate:
text
Ctrl+F37. Why the field is nullable
Old rows have no Lesson 15 owner value.
A nullable field allows the table to evolve without rebuilding old data.
New Lesson 15 rows will deliberately supply:
text
ResponsibleUserfor authorization tests.
8. Add ResponsibleUser to the root CDS
Open:
text
ZR_RESERVATION_###Add:
abap
Reservation.responsible_user as ResponsibleUser,Place it with the business fields.
9. Change the CDS access-control annotation
Change:
abap
@AccessControl.authorizationCheck: #NOT_REQUIREDto:
abap
@AccessControl.authorizationCheck: #CHECKThe root is now intended to participate in CDS access-control evaluation.
10. Existing rows may disappear from root preview
Older rows may have:
text
ResponsibleUser = initialOnce DCL becomes active, they will not satisfy:
text
ResponsibleUser = current userThey may disappear from:
text
F8 root CDS previewThat is not data loss.
They still exist in persistence.
11. What is DCL?
DCL means:
text
Data Control LanguageA CDS Access Control object defines row-level read restrictions.
Mental model:
text
normal CDS selection
+
DCL condition
=
authorized result set12. Create an Access Control object
In ADT:
text
Right-click package
→ New
→ Other ABAP Repository Object
→ Core Data Services
→ Access ControlUse:
text
Name: ZR_RESERVATION_###
Description: Reservation Read Access13. Define the CDS role
Use:
abap
@EndUserText.label: 'Reservation Read Access'
@MappingRole: true
define role ZR_Reservation_###
{
grant select on ZR_Reservation_###
where ResponsibleUser = aspect user;
}Replace ###.
14. @MappingRole: true
This annotation makes the CDS role participate in implicit access-control evaluation for users.
It is not the same thing as:
text
assigning a PFCG/business role to one userThose are different authorization concepts.
15. grant select on
The role grants read access to:
text
ZR_RESERVATION_###only where:
text
ResponsibleUser = logged-on userRows that fail the rule are filtered from normal protected reads.
16. aspect user
This condition:
abap
ResponsibleUser = aspect usercompares ResponsibleUser with the current authenticated ABAP user.
Do not hard-code:
text
MYUSER
STUDENT01into authorization logic.
17. Activate the Access Control
Run:
text
Ctrl+F2
Ctrl+F3Verify:
text
Root CDS active
Access Control active18. DCL is implicit
Normal protected consumers do not call a special:
text
CHECK DCLstatement.
The access condition participates automatically when the protected CDS entity is read.
19. DCL does not replace write authorization
DCL answers:
text
Can the user read this row?It does not replace RAP behavior authorization for:
text
update
delete
actionsSo the lesson now adds RAP authorization too.
20. Enable RAP global + instance authorization
Open the BDEF.
Replace:
abap
authorization master ( none )with:
abap
authorization master ( global, instance )This makes the Reservation root the authorization master.
21. Global authorization
Global authorization asks:
text
Can this user perform this operation in general?Examples:
text
May this user create Reservations?
May this user generally update Reservations?
May this user generally delete Reservations?It does not depend on one particular Reservation.
22. Instance authorization
Instance authorization asks:
text
Can this user perform the operation
on this particular Reservation?It may depend on fields of the instance.
Today:
text
ResponsibleUserdrives the update decision.
23. Authorization result constants
Use:
abap
if_abap_behv=>auth-allowedand:
abap
if_abap_behv=>auth-unauthorizedDo not use feature-control constants for authorization results.
24. Feature vs authorization constant families
Feature control:
text
if_abap_behv=>fc-o-...
if_abap_behv=>fc-f-...Authorization:
text
if_abap_behv=>auth-allowed
if_abap_behv=>auth-unauthorizedThis distinction matters in practical repair work.
25. Map ResponsibleUser
Add to BDEF persistence mapping:
abap
ResponsibleUser = responsible_user;26. Protect owner reassignment
Add:
abap
field ( readonly:update ) ResponsibleUser;For this lesson:
text
CREATE
→ consumer may assign ResponsibleUser
UPDATE
→ ResponsibleUser cannot be reassigned normally27. Make Status read-only if necessary
If your current BDEF still allows ordinary external Status updates, change it so Status is read-only.
Status should be changed by:
text
setInitialStatus
confirm
cancelnot arbitrary normal update requests.
28. Delegate action authorization to update
Change the actions to:
abap
action ( features : instance, authorization: update )
confirm result [1] $self;
action ( features : instance, authorization: update )
cancel result [1] $self;The actions still keep:
text
features : instancefor state-based availability.
Authorization is delegated separately.
29. Why keep both feature and authorization control?
For confirm:
text
Feature question:
Is Status = N?
Authorization question:
Is current user ResponsibleUser?An operation must respect both concerns.
30. Generate authorization handler methods
Use:
text
Ctrl+1from the BDEF.
Generate methods equivalent to:
abap
METHODS get_global_authorizations
FOR GLOBAL AUTHORIZATION
IMPORTING
REQUEST requested_authorizations FOR Reservation
RESULT result.
METHODS get_instance_authorizations
FOR INSTANCE AUTHORIZATION
IMPORTING
keys
REQUEST requested_authorizations FOR Reservation
RESULT result.Prefer ADT-generated signatures.
31. Productive authorization vs Trial authorization
Productive RAP authorization often evaluates:
text
authorization objects
business roles
activity values
organizational restrictions
released authorization APIsThe course needs a reproducible BTP Trial exercise.
Therefore:
text
global authorization
→ allow-all training implementation
instance authorization
→ real current-user ownership comparison32. Certification knowledge — not reproducible in BTP Trial
Certification knowledge — not reproducible in BTP Trial
SAP RAP examples commonly connect authorization handlers to real authorization objects or helper APIs.
A productive check can distinguish activities such as:
text
create
change
deleteThe Trial course does not provision a custom PFCG authorization object and role assignment landscape for each student.
Understand where those checks belong even though the full administration scenario is not reproduced here.
33. Implement global authorization
Use:
abap
METHOD get_global_authorizations.
IF requested_authorizations-%create = if_abap_behv=>mk-on.
result-%create = if_abap_behv=>auth-allowed.
ENDIF.
IF requested_authorizations-%update = if_abap_behv=>mk-on.
result-%update = if_abap_behv=>auth-allowed.
ENDIF.
IF requested_authorizations-%delete = if_abap_behv=>mk-on.
result-%delete = if_abap_behv=>auth-allowed.
ENDIF.
ENDMETHOD.This proves the RAP global-authorization contract.
It is intentionally not a productive role design.
34. Why inspect requested_authorizations?
The framework tells you which permissions are currently requested.
Pattern:
text
requested?
→ calculate authorization
not requested?
→ do not do unnecessary work35. Obtain the current technical user
Use:
abap
cl_abap_context_info=>get_user_technical_name( )Store the value in a compatible user variable:
abap
DATA current_user TYPE abp_creation_user.
current_user = cl_abap_context_info=>get_user_technical_name( ).36. Instance authorization rule
Use:
text
UPDATE
ResponsibleUser = current technical user
→ allowed
otherwise
→ unauthorizedFor classroom cleanup:
text
DELETE
→ allowed37. Why delete is allowed today
This is a deliberate training simplification.
You will create an intentionally unauthorized/unassigned Reservation.
If delete were also owner-only, repeatable reset would be awkward.
A productive system should define delete authorization according to its real business policy.
38. Read ownership inside the authorization handler
Use:
abap
READ ENTITIES OF ZR_Reservation_### IN LOCAL MODE
ENTITY Reservation
FIELDS ( ResponsibleUser )
WITH CORRESPONDING #( keys )
RESULT DATA(reservations)
FAILED failed.The handler needs current BO state to calculate instance authorization.
39. Implement instance authorization
Use a pattern equivalent to:
abap
METHOD get_instance_authorizations.
READ ENTITIES OF ZR_Reservation_### IN LOCAL MODE
ENTITY Reservation
FIELDS ( ResponsibleUser )
WITH CORRESPONDING #( keys )
RESULT DATA(reservations)
FAILED failed.
DATA current_user TYPE abp_creation_user.
current_user = cl_abap_context_info=>get_user_technical_name( ).
LOOP AT reservations INTO DATA(reservation).
APPEND VALUE #(
%tky = reservation-%tky
) TO result ASSIGNING FIELD-SYMBOL(<authorization>).
IF requested_authorizations-%update = if_abap_behv=>mk-on.
<authorization>-%update =
COND #(
WHEN reservation-ResponsibleUser = current_user
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized
).
ENDIF.
IF requested_authorizations-%delete = if_abap_behv=>mk-on.
<authorization>-%delete = if_abap_behv=>auth-allowed.
ENDIF.
ENDLOOP.
ENDMETHOD.40. Add an authorization message
When update is unauthorized, add a message equivalent to:
abap
APPEND VALUE #(
%tky = reservation-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'You are not responsible for this reservation'
)
) TO reported-reservation.The authorization decision still comes from:
text
auth-unauthorizedThe message explains it.
41. Why actions need no separate owner comparison
Because:
text
confirm authorization = update authorization
cancel authorization = update authorizationvia:
text
authorization: updateone owner rule protects:
text
normal update
confirm
cancel42. Activate the full authorization model
Use:
text
Ctrl+F2
Ctrl+Shift+F3Verify:
text
ZRESV_###
ZR_RESERVATION_###
Access Control
Behavior Definition
ZBP_R_RESV_###all activate.
43. Create ZCL_RESV_AUTH_###
Create an ABAP class implementing:
text
IF_OO_ADT_CLASSRUNThis class is an external consumer.
Do not use:
text
IN LOCAL MODEinside it.
44. Reserved test numbers
Use:
text
98000001
98000002Meaning:
text
98000001
→ owned by current user
98000002
→ ResponsibleUser initial45. Repeatable reset with DCL present
DCL can hide one training row.
For reset only, you may use a read-only persistence lookup to discover UUIDs for exactly:
text
98000001
98000002Then:
text
delete those UUIDs through EML
commitNo direct SQL write is allowed.
46. Display the current user
In the consumer:
abap
DATA current_user TYPE abp_creation_user.
current_user = cl_abap_context_info=>get_user_technical_name( ).
out->write( |Current user: { current_user }| ).47. Create the owned Reservation
Create valid Lesson 13 data with:
text
ReservationNo = 98000001
ResponsibleUser = current user
Status = omittedThe Lesson 13 determination should default:
text
Status = NUse:
text
%cid = OWNED48. Create the unassigned Reservation
Create another valid Reservation:
text
ReservationNo = 98000002
ResponsibleUser = initial
Status = omittedUse:
text
%cid = UNASSIGNEDSave both UUIDs from:
text
MAPPEDbefore commit.
49. Commit both creates
Use:
text
COMMIT ENTITIESExpected:
text
both create operations save successfullybecause global create authorization is allowed.
50. DCL proof with F8
Open:
text
ZR_RESERVATION_###with:
text
F8Expected:
text
98000001 visible
98000002 hiddenThe DCL condition is true only for the owned row.
51. Persistence proof with Alt+F8
Open:
text
ZRESV_###with:
text
Alt+F8Expected:
text
98000001 exists
98000002 existsThis proves:
text
DCL filters reads
DCL does not delete rows52. Create a global permission request
Use:
abap
DATA global_request
TYPE STRUCTURE FOR PERMISSIONS REQUEST ZR_Reservation_###.
global_request-%create = if_abap_behv=>mk-on.
global_request-%update = if_abap_behv=>mk-on.
global_request-%delete = if_abap_behv=>mk-on.53. GET PERMISSIONS — global authorization
Use:
abap
GET PERMISSIONS ONLY GLOBAL AUTHORIZATION
ENTITY ZR_Reservation_###
REQUEST global_request
RESULT DATA(global_permissions)
FAILED DATA(failed_global)
REPORTED DATA(reported_global).Output all three response structures.
Expected training result:
text
create allowed
update allowed
delete allowed54. Create an instance authorization request
Use:
abap
DATA instance_request
TYPE STRUCTURE FOR PERMISSIONS REQUEST ZR_Reservation_###.
instance_request-%update = if_abap_behv=>mk-on.
instance_request-%delete = if_abap_behv=>mk-on.55. GET PERMISSIONS — owned Reservation
Use:
abap
GET PERMISSIONS ONLY INSTANCE AUTHORIZATION
ENTITY ZR_Reservation_###
FROM VALUE #(
( Uuid = uuid_owned )
)
REQUEST instance_request
RESULT DATA(auth_owned)
FAILED DATA(failed_auth_owned)
REPORTED DATA(reported_auth_owned).Expected:
text
update allowed
delete allowed56. GET PERMISSIONS — unassigned Reservation
Repeat using:
text
uuid_unassignedExpected:
text
update unauthorized
delete allowed57. Ask for Lesson 14 instance features too
For the unassigned Reservation:
text
Status = NRequest its instance features.
Expected:
text
confirm feature = enabledbecause Status allows it.
58. Compare feature control and authorization
For the same unassigned row:
text
Feature:
confirm enabled
Authorization:
update unauthorizedBecause the action delegates authorization to update:
text
confirm must still be deniedThis is the central Lesson 15 runtime observation.
59. Confirm the owned Reservation
Execute:
text
confirmfor:
text
98000001Expected:
text
action succeeds
Status N → C
COMMIT succeeds60. Attempt confirm on the unassigned Reservation
Execute:
text
confirmusing the known UUID for:
text
98000002Expected:
text
authorization denies execution
Status remains N
message explains the denialThe feature may be enabled, but authorization wins.
61. Attempt a normal UPDATE on the unassigned row
Try:
text
Notes = 'Unauthorized update attempt'Expected:
text
update denied
persisted Notes unchangedInspect:
text
FAILED
REPORTEDand the permission result.
62. Cleanup the unassigned training row
Delete:
text
98000002through EML using its known UUID.
Delete authorization is deliberately allowed.
Commit.
63. Final guided state
Keep:
text
98000001for inspection.
Expected:
text
ResponsibleUser = current user
Status = C64. aspect user vs aspect pfcg_auth
Today you used:
text
aspect userDCL can also use:
text
aspect pfcg_authto evaluate PFCG authorization data.
65. Certification knowledge — PFCG-based DCL
Certification knowledge — not reproducible in BTP Trial
A productive DCL can use a PFCG condition conceptually shaped like:
text
(Field) = aspect pfcg_auth(
authorization_object,
authorization_field,
ACTVT = '03'
)Our Trial course does not provision custom productive authorization objects and business-role assignments.
Know the purpose and location of the mechanism.
66. CDS role is not a PFCG role
This:
abap
define role ...creates a CDS DCL access-control artifact.
It is not the same as:
text
a business role
a PFCG roleDo not confuse the shared word:
text
role67. Why authorization implementation uses local mode
The provider needs BO data to calculate authorization.
Without provider-local access, you can create circular reasoning:
text
need authorization to read
need data to calculate authorizationThe handler uses:
text
READ ENTITIES ... IN LOCAL MODEto inspect its own BO state.
68. Local mode belongs to providers
Provider:
text
Behavior Pool
authorization method
IN LOCAL MODEExternal consumer:
text
ZCL_RESV_AUTH_###
normal EMLNever use local mode to bypass authorization from normal application code.
69. DCL debugging
If a row disappears:
text
check ResponsibleUser
check current user
check @MappingRole
check #CHECK
check DCL entity name
check DCL activationThen compare:
text
F8 root
Alt+F8 table70. RAP authorization debugging
If a modification is denied:
text
GET PERMISSIONS global
GET PERMISSIONS instance
ResponsibleUser
requested_authorizations
FAILED
REPORTED
feature resultDo not assume the feature matrix is the authorization matrix.
71. Global allowed + instance denied is valid
Example:
text
global update = allowed
instance update = unauthorizedMeaning:
text
user may update Reservations generally
but not this ReservationNo contradiction exists.
72. Feature enabled + authorization denied is valid
Example:
text
Status = N
→ confirm feature enabled
ResponsibleUser <> current user
→ update authorization deniedThe final operation is denied.
73. Certification alignment
The current Backend Developer – ABAP Cloud certification is practical/system-based.
Authorization-related tasks can therefore reward the ability to:
text
create/repair DCL
change CDS authorization annotation
change BDEF authorization declaration
generate handler methods
fill RAP authorization result
use GET PERMISSIONS
activate dependent artifacts
test runtime behaviorHands-on ADT fluency matters more than memorizing definitions.
74. Practical repair decision tree
text
Wrong rows visible?
→ DCL / #CHECK / DCL condition
All writes denied?
→ global authorization
Only some instances denied?
→ instance authorization
Action greyed/disabled because of state?
→ feature control
Action business state okay but still denied?
→ authorization75. Knowledge check
1. What is DCL?
2. What does aspect user do?
3. Why does the root change to #CHECK?
4. What is the difference between a CDS role and a PFCG role?
5. What is global authorization?
6. What is instance authorization?
7. Why do actions delegate to update authorization here?
8. What is the difference between auth-unauthorized and fc-o-disabled?
9. Why can an instance exist in the table but not appear in root Data Preview?
10. Why can feature control allow an action while authorization denies it?
11. Why does provider authorization code use local mode?
12. Why is real PFCG administration marked as certification knowledge in this course?
76. Teacher-led completion checklist
77. End-of-day mental model
text
USER
│
┌────────┴────────┐
│ │
READ MODIFY
│ │
DCL RAP Authorization
│ ┌──────┴──────┐
│ Global Instance
│ │ │
└──────────┴──────┬───────┘
↓
RAP Business Object
↓
PersistenceRemember:
text
DCL
→ Which rows can I read?
Global authorization
→ May this user perform this operation in general?
Instance authorization
→ May this user perform it on this instance?
Feature control
→ Is the operation meaningful for the current business state?Lesson 16 adds:
text
Projection
Value Help
Metadata
Service Definition
Service Binding
OData V4