RAP Authorization: Implementing Permissions in ABAP Cloud

Category
RAP
Published
Author
Johannes

Authorization in RAP ensures that users can only access data and execute operations they are authorized for. This article shows the different authorization concepts and their implementation.

Authorization Concepts Overview

AspectInstance AuthorizationGlobal Authorization
ScopeIndividual instancesEntire entity
CheckPer recordOnce per operation
Use case”May user edit this travel?""May user create travels at all?”
PerformanceMore expensive (per instance)More efficient (once)

Instance Authorization

Instance Authorization checks permissions at the level of individual records. This is important when different instances have different authorization requirements.

Behavior Definition

managed implementation in class zbp_i_travel unique;
strict ( 2 );
define behavior for ZI_Travel alias Travel
persistent table ztravel
lock master
authorization master ( instance )
{
create;
update;
delete;
action cancel result [1] $self;
action accept result [1] $self;
mapping for ztravel
{
TravelUUID = travel_uuid;
TravelID = travel_id;
AgencyID = agency_id;
CustomerID = customer_id;
Status = overall_status;
}
}

Implementation of Instance Authorization

CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR Travel RESULT result.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD get_instance_authorizations.
" Read instance data
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( AgencyID Status )
WITH CORRESPONDING #( keys )
RESULT DATA(travels).
LOOP AT travels ASSIGNING FIELD-SYMBOL(<travel>).
" Check authorization object
DATA(is_authorized_update) = abap_false.
DATA(is_authorized_delete) = abap_false.
DATA(is_authorized_cancel) = abap_false.
" Check update authorization
IF requested_authorizations-%update = if_abap_behv=>mk-on
OR requested_authorizations-%action-cancel = if_abap_behv=>mk-on.
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD <travel>-AgencyID
ID 'ACTVT' FIELD '02'. " Change
IF sy-subrc = 0.
is_authorized_update = abap_true.
is_authorized_cancel = abap_true.
ENDIF.
ENDIF.
" Check delete authorization
IF requested_authorizations-%delete = if_abap_behv=>mk-on.
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD <travel>-AgencyID
ID 'ACTVT' FIELD '06'. " Delete
IF sy-subrc = 0.
is_authorized_delete = abap_true.
ENDIF.
ENDIF.
" Additional status check for Cancel action
IF is_authorized_cancel = abap_true
AND <travel>-Status <> 'O'. " Only open travels
is_authorized_cancel = abap_false.
ENDIF.
" Set result
APPEND VALUE #(
%tky = <travel>-%tky
%update = COND #(
WHEN is_authorized_update = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
%delete = COND #(
WHEN is_authorized_delete = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
%action-cancel = COND #(
WHEN is_authorized_cancel = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
) TO result.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

Authorization Return Values

ValueMeaning
if_abap_behv=>auth-allowedOperation allowed
if_abap_behv=>auth-unauthorizedNo authorization

Global Authorization

Global Authorization checks permissions at entity level, independent of concrete instances. Ideal for CREATE operations or when all instances are treated equally.

Behavior Definition

define behavior for ZI_Travel alias Travel
persistent table ztravel
lock master
authorization master ( global )
{
create;
update;
delete;
static action massUpdate;
}

Implementation of Global Authorization

CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION
IMPORTING REQUEST requested_authorizations FOR Travel RESULT result.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD get_global_authorizations.
" Check CREATE authorization
IF requested_authorizations-%create = if_abap_behv=>mk-on.
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' DUMMY
ID 'ACTVT' FIELD '01'. " Create
DATA(is_create_authorized) = COND #(
WHEN sy-subrc = 0
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized ).
ENDIF.
" Check static action authorization
IF requested_authorizations-%action-massUpdate = if_abap_behv=>mk-on.
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' DUMMY
ID 'ACTVT' FIELD '02'.
DATA(is_mass_update_authorized) = COND #(
WHEN sy-subrc = 0
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized ).
ENDIF.
result = VALUE #(
%create = is_create_authorized
%action-massUpdate = is_mass_update_authorized
).
ENDMETHOD.
ENDCLASS.

Combined Authorization (Instance + Global)

In practice, both types of authorization are often needed:

Behavior Definition

define behavior for ZI_Travel alias Travel
persistent table ztravel
lock master
authorization master ( instance, global )
{
create;
update;
delete;
action cancel result [1] $self;
static action releaseAll;
}

Implementation

CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
" Instance Authorization for UPDATE, DELETE, Actions
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR Travel RESULT result.
" Global Authorization for CREATE and Static Actions
METHODS get_global_authorizations FOR GLOBAL AUTHORIZATION
IMPORTING REQUEST requested_authorizations FOR Travel RESULT result.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD get_instance_authorizations.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( AgencyID )
WITH CORRESPONDING #( keys )
RESULT DATA(travels).
LOOP AT travels ASSIGNING FIELD-SYMBOL(<travel>).
" Agency-based authorization
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD <travel>-AgencyID
ID 'ACTVT' FIELD '02'.
DATA(has_change_auth) = COND #( WHEN sy-subrc = 0 THEN abap_true ).
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD <travel>-AgencyID
ID 'ACTVT' FIELD '06'.
DATA(has_delete_auth) = COND #( WHEN sy-subrc = 0 THEN abap_true ).
APPEND VALUE #(
%tky = <travel>-%tky
%update = COND #(
WHEN has_change_auth = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
%delete = COND #(
WHEN has_delete_auth = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
%action-cancel = COND #(
WHEN has_change_auth = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
) TO result.
ENDLOOP.
ENDMETHOD.
METHOD get_global_authorizations.
" CREATE authorization
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' DUMMY
ID 'ACTVT' FIELD '01'.
DATA(create_auth) = COND #(
WHEN sy-subrc = 0
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized ).
" Static action authorization
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' DUMMY
ID 'ACTVT' FIELD '02'.
DATA(release_auth) = COND #(
WHEN sy-subrc = 0
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized ).
result = VALUE #(
%create = create_auth
%action-releaseAll = release_auth
).
ENDMETHOD.
ENDCLASS.

Authorization Master and Dependent

With compositions having parent-child relationships, authorization can be delegated from the parent.

Behavior Definition

define behavior for ZI_Travel alias Travel
persistent table ztravel
lock master
authorization master ( instance )
{
create;
update;
delete;
association _Booking { create; }
}
define behavior for ZI_Booking alias Booking
persistent table zbooking
lock dependent by _Travel
authorization dependent by _Travel
{
update;
delete;
field ( readonly ) TravelUUID;
association _Travel;
}

Explanation

  • authorization master: This entity performs the authorization check
  • authorization dependent by _Travel: Booking inherits authorization from Travel
  • For operations on Booking, Travel’s authorization is automatically checked

Advantage

No separate authorization implementation needed for Booking. The parent authorization applies automatically to all dependent entities.

Precheck for Early Authorization Checking

With Precheck, authorizations can be checked before the actual operation is executed. This is more efficient as invalid requests are rejected early.

Behavior Definition

define behavior for ZI_Travel alias Travel
persistent table ztravel
lock master
authorization master ( instance )
{
create ( precheck );
update ( precheck );
delete ( precheck );
action ( precheck ) cancel result [1] $self;
}

Implementation with Precheck

CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
METHODS precheck_create FOR PRECHECK
IMPORTING entities FOR CREATE Travel.
METHODS precheck_update FOR PRECHECK
IMPORTING entities FOR UPDATE Travel.
METHODS precheck_cancel FOR PRECHECK
IMPORTING keys FOR ACTION Travel~cancel.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD precheck_create.
LOOP AT entities ASSIGNING FIELD-SYMBOL(<entity>).
" Check authorization for new agency
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD <entity>-AgencyID
ID 'ACTVT' FIELD '01'.
IF sy-subrc <> 0.
APPEND VALUE #(
%cid = <entity>-%cid
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = |No authorization for agency { <entity>-AgencyID }|
)
) TO reported-travel.
APPEND VALUE #( %cid = <entity>-%cid ) TO failed-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD precheck_update.
" Read current data
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( AgencyID Status )
WITH CORRESPONDING #( entities )
RESULT DATA(travels).
LOOP AT entities ASSIGNING FIELD-SYMBOL(<entity>).
READ TABLE travels INTO DATA(travel)
WITH KEY TravelUUID = <entity>-TravelUUID.
" Locked travels cannot be edited
IF travel-Status = 'L'. " Locked
APPEND VALUE #(
%tky = <entity>-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Locked travels cannot be edited'
)
) TO reported-travel.
APPEND VALUE #( %tky = <entity>-%tky ) TO failed-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.
METHOD precheck_cancel.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
FIELDS ( Status )
WITH CORRESPONDING #( keys )
RESULT DATA(travels).
LOOP AT travels ASSIGNING FIELD-SYMBOL(<travel>).
" Only open travels can be cancelled
IF <travel>-Status <> 'O'.
APPEND VALUE #(
%tky = <travel>-%tky
%msg = new_message_with_text(
severity = if_abap_behv_message=>severity-error
text = 'Only open travels can be cancelled'
)
) TO reported-travel.
APPEND VALUE #( %tky = <travel>-%tky ) TO failed-travel.
ENDIF.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

Interaction with Feature Control

Authorization and Feature Control complement each other:

AspectAuthorizationFeature Control
PurposeCheck permissionControl UI elements
ResultAllowed/UnauthorizedEnabled/Disabled
TimingAt executionWhen loading UI

Best Practice: Consistent Checking

CLASS lhc_travel DEFINITION INHERITING FROM cl_abap_behavior_handler.
PRIVATE SECTION.
" Feature Control
METHODS get_instance_features FOR INSTANCE FEATURES
IMPORTING keys REQUEST requested_features FOR Travel RESULT result.
" Authorization
METHODS get_instance_authorizations FOR INSTANCE AUTHORIZATION
IMPORTING keys REQUEST requested_authorizations FOR Travel RESULT result.
" Shared helper method
METHODS check_cancel_allowed
IMPORTING travel TYPE zi_travel
RETURNING VALUE(result) TYPE abap_boolean.
ENDCLASS.
CLASS lhc_travel IMPLEMENTATION.
METHOD check_cancel_allowed.
" Central logic for Feature Control AND Authorization
result = abap_false.
" Only open travels
IF travel-Status <> 'O'.
RETURN.
ENDIF.
" Authorization check
AUTHORITY-CHECK OBJECT 'ZTRAVEL'
ID 'ZAGENCY' FIELD travel-AgencyID
ID 'ACTVT' FIELD '02'.
IF sy-subrc = 0.
result = abap_true.
ENDIF.
ENDMETHOD.
METHOD get_instance_features.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(travels).
LOOP AT travels ASSIGNING FIELD-SYMBOL(<travel>).
DATA(can_cancel) = check_cancel_allowed( <travel> ).
APPEND VALUE #(
%tky = <travel>-%tky
%action-cancel = COND #(
WHEN can_cancel = abap_true
THEN if_abap_behv=>fc-o-enabled
ELSE if_abap_behv=>fc-o-disabled )
) TO result.
ENDLOOP.
ENDMETHOD.
METHOD get_instance_authorizations.
READ ENTITIES OF zi_travel IN LOCAL MODE
ENTITY Travel
ALL FIELDS
WITH CORRESPONDING #( keys )
RESULT DATA(travels).
LOOP AT travels ASSIGNING FIELD-SYMBOL(<travel>).
DATA(can_cancel) = check_cancel_allowed( <travel> ).
APPEND VALUE #(
%tky = <travel>-%tky
%action-cancel = COND #(
WHEN can_cancel = abap_true
THEN if_abap_behv=>auth-allowed
ELSE if_abap_behv=>auth-unauthorized )
) TO result.
ENDLOOP.
ENDMETHOD.
ENDCLASS.

Authorization Objects in ABAP Cloud

In ABAP Cloud, authorization objects are created with ADT:

  1. Create Package for authorization
  2. Create Authorization Object (Transaction SU21 doesn’t exist)
  3. Define Authorization Fields
  4. Check in code with AUTHORITY-CHECK OBJECT

Example Authorization Object

Authorization Object: ZTRAVEL
Fields:
- ZAGENCY (Agency ID)
- ZREGION (Region Code)
- ACTVT (Activity: 01=Create, 02=Change, 03=Display, 06=Delete)

Best Practices

  1. Global for CREATE: Always use Global Authorization for CREATE operations, as no instance exists yet.

  2. Instance for UPDATE/DELETE: When permissions depend on instance data (e.g., agency, region).

  3. Dependent for Compositions: Child entities inherit authorization from parent.

  4. Keep Feature Control in sync: Disabled buttons should also be unauthorized.

  5. Use Precheck: For early validation and better error messages.

  6. Extract helper methods: Move shared checking logic into reusable methods.

  7. DUMMY for generic checks: Use ID 'ZAGENCY' DUMMY when the concrete value doesn’t matter.