Using the AUTHORITY-CHECK Statement

Objective

After completing this lesson, you will be able to Use the AUTHORITY-CHECK statement.

The AUTHORITY-CHECK Statement

To perform an authorization check explicitly, you use the AUTHORITY-CHECK statement. In it, you specify the authorization object against which you want to check, along with the required values. The AUTHORITY-CHECK here performs a check against object /DMO/TRVL and requires the user to have an authorization containing the value US for field CNTRY and 03 for field ACTVT.

How to Check the Result of the Authorization Check

Unlike the filtered authorization checks that come with CDS access controls, the AUTHORITY-CHECK statement does not prevent users from seeing data for which they have no authorization.

AUTHORITY-CHECK places a return code in the system field sy-subrc. By checking the value of sy-subrc immediately after the authorization check, you can find out whether the check was successful or not.

If the authorization check was successful, sy-subrc has the value 0. Other values of sy-subrc mean that the check has failed:

  • The value 4 means that the user has an authorization for the corresponding object, but not the right values.
  • The value 12 means that the user does not have an authorization for the corresponding object at all.

If the authorization check fails, you must ensure yourself that the user cannot access the data.

In the example, the authorization check requires the user to have an authorization for country 'US'. Since that is not the case for our user, sy-subrc is unequal to zero after the authorization check. In this case, the app displays the text No authorization'.

How to Use the AUTHORITY-CHECK Statement

Watch this video to know how to use the Authority-Check statement.

Implement Authority Checks

You realize that your code gives users access to data which they are not authorized to see. To amend this you first let your code read from CDS view entities for which CDS access controls are defined. Then you implement an explicit authority check to be able to distinguish between data the user is not authorized to see and data that does not exist at all.

Template:

  • /LRN/CL_S4D401_ITS_SEC_KEY (Global Class)

Solution:

  • /LRN/CL_S4D401_ACS_AUTH_CHECK (Global Class)

Task 1: Copy Template (Optional)

Copy the template class. If you finished the previous exercise, you can skip this task and continue editing your class ZCL_##_SOLUTION.

Steps

  1. Copy class /LRN/CL_S4D401_ITS_SEC_KEY to a class in your own package (suggested name: ZCL_##_SOLUTION, where ## stands for your group number).

    1. In the Project Explorer view, right-click class /LRN/CL_S4D401_ITS_SEC_KEY to open the context menu.

    2. From the context menu, choose Duplicate ....

    3. Enter the name of your package in the Package field. In the Name field, enter the name ZCL_##_SOLUTION, where ## stands for your group number.

    4. Adjust the description and choose Next.

    5. Confirm the transport request and choose Finish.

  2. Activate the copy.

    1. Press Ctrl + F3 to activate the class.

Task 2: Analyze Authorizations

Starting from database table /LRN/CARRIER, find the CDS access control that protects carrier data against unauthorized access. Analyze the CDS access control to find out which authorizations a user needs to display carrier data.

Steps

  1. Display the definition of database table /LRN/CARRIER.

    1. Press Ctrl + Shift + A and enter /LRN/CARRIER.

  2. Analyze the Where-used list for this database table .

    1. In the definition of database table /LRN/CARRIER, right-click on /LRN/CARRIER and choose Get Where-Used List.

    2. Alternatively, click on /LRN/CARRIER and press Ctrl + Shift + G.

    3. In the Search view below the editor, Choose the funnel icon to open the filter dialog.

    4. Place the cursor in the Object Type(s): field and press Ctrl + Space to open a value help dialog.

    5. From the suggestion list, choose value DDLS/DF (Data Definition) and choose Apply.

  3. Analyze the Where-used list for these CDS views.

    1. In the Search view, right-click on /LRN/I_CARRIER (Data Definition) and choose Get Where-Used List.

    2. Alternatively, click on /LRN/I_CARRIER (Data Definition) and press Ctrl + Shift + G.

    3. If the Search view below the editor displays too many hits, choose the funnel icon to open the filter dialog.

    4. Place the cursor in the Object Type(s): field and press Ctrl + Space to open a value help dialog.

    5. From the suggestion list, choose value DCLS/DL (Access Control) and choose Apply.

  4. Open the definition of access control /LRN/I_CARRIER.

    1. In the Search view, double click /LRN/I_CARRIER (Access Control).

    2. The authorization object name is the first input parameter for function pfcg_auth.

    3. The other input parameters supply values for the authorization fields of the authorization object.

  5. Open the definition of the authorization object(s) to analyze the meaning of the activity values.

    1. Hold down the Ctrl key and choose the name of the authorization object (that is, the mention of /LRN/CARR in the call of function pfcg_auth).

    2. The possible activity values are listed under Permitted Activities.

Task 3: Use CDS Access Control

In the constructor method of local class LCL_CARRIER, replace database table /LRN/CARRIER with CDS view entity /LRN/I_Carrier, which is protected by CDS access control /LRN/I_CARRIER. Test the code with different carrier IDs as constructor input.

Steps

  1. Open the implementation of the constructor method of local class LCL_CARRIER.

    1. Return to the code of your global class ZCL_##_SOLUTION, where ## is your group number.

    2. Either search on the Local Types tab or expand LCL_CARRIERCONSTRUCTOR in the Outline view and double-click CONSTRUCTOR.

  2. Adjust the SELECT statement. In the FROM clause, replace database table /DMO/CARRIER with the CDS view entity you just found.

    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      123
      SELECT SINGLE * FROM /lrn/carrier
  3. Fix the syntax errors. Replace the table field names with the corresponding CDS view element names.

    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      123456789
      * SELECT SINGLE * FROM /lrn/carrier * FIELDS concat_with_space( carrier_id, name, 1 ) , currency_code * WHERE carrier_id = @i_carrier_id * INTO ( @me->name, @me->currency_code ). SELECT SINGLE FROM /lrn/i_carrier
  4. Activate and test your global class as console app.

    1. Press Ctrl + F3.

    2. Press F9.

  5. In your global class, change the value of local constant c_carrier_id to UA.

    1. Switch to the Global Class tab.

    2. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      12
      * CONSTANTS c_carrier_id TYPE /dmo/carrier_id VALUE 'LH'.
  6. Activate and test your global class as console app.

    1. Press Ctrl + F3.

    2. Press F9.

Task 4: Implement an AUTHORITY-CHECK Statement

In the constructor method of local class LCL_CARRIER, implement an AUTHORITY-CHECK statement and raise exception CX_ABAP_AUTH_CHECK_EXCEPTION if the flight carrier exists but the user is not authorized for this carrier.

Steps

  1. Open the implementation of the constructor method of local class LCL_CARRIER.

    1. Return to the code of your global class ZCL_##_SOLUTION, where ## is your group number.

    2. Either search on the Local Types tab or expand LCL_CARRIERCONSTRUCTOR in the Outline view and double-click CONSTRUCTOR.

  2. Adjust the SELECT statement to read from database table database table /DMO/CARRIER again.

    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      1234567
      * SELECT SINGLE * FROM /lrn/i_carrier * FIELDS concat_with_space( airlineid, name, 1 ) , currencycode * WHERE airlineid = @i_carrier_id * INTO ( @me->name, @me->currency_code ).
  3. Implement an AUTHORITY-CHECK statement that is performed if the read access was successful, that is if exception CX_ABAP_INVALID_VALUE has not been raised. Use the authorization object, authorization fields and values you found earlier.

    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      1234567891011121314
      IF sy-subrc <> 0. RAISE EXCEPTION TYPE cx_abap_invalid_value. ENDIF. AUTHORITY-CHECK OBJECT '/LRN/CARR' ID '/LRN/CARR' FIELD i_carrier_id ID 'ACTVT' FIELD '03'. IF sy-subrc <> 0. ENDIF.
  4. If the user does not have the display authorization for the requested airline ID raise exception CX_ABAP_AUTH_CHECK_EXCEPTION.

    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      123456789
      AUTHORITY-CHECK OBJECT '/LRN/CARR' ID '/LRN/CARR' FIELD i_carrier_id ID 'ACTVT' FIELD '03'. IF sy-subrc <> 0. ENDIF.
  5. Use a quick fix to add the exception to the RAISING clause of the method definition.

    1. In the RAISE EXCEPTION statement, click on cx_abap_auth_check_exception and press Ctrl + 1.

    2. Alternatively, choose the light-bulb icon left from the code row with the syntax warning.

    3. From the list of suggested quick fixes, choose Add raising declaration.

    4. As result, the definition of the CONSTRUCTOR method should now look like this:

      Code Snippet
      Copy code
      Switch to dark mode
      1234567
      METHODS constructor IMPORTING i_carrier_id TYPE /dmo/carrier_id RAISING cx_abap_invalid_value.
  6. In your global class, extend the TRY … ENDTRY control structure with a CATCH block for the new exception. Issue a suitable text to indicate that user is not authorized to display the carrier.

    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      12345678910
      TRY. DATA(carrier) = NEW lcl_carrier( i_carrier_id = c_carrier_id ). out->write( name = `Carrier Overview` data = carrier->get_output( ) ). CATCH cx_abap_invalid_value. out->write( | Carrier { c_carrier_id } does not exist | ). ENDTRY.
  7. Similarly, extend the TRY … ENDTRY control structure in the class_setup method of your local unit test class. Use the same implementation as in the catch block for exception CX_ABAP_INVALID_VALUE.

    Note

    This is just a workaround. Later I this course, you will learn how to handle several exceptions in the same catch block.
    1. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      1234567
      TRY. the_carrier = NEW lcl_carrier( i_carrier_id = some_flight_data-carrier_id ). CATCH cx_abap_invalid_value. cl_abap_unit_assert=>fail( `Unable to instantiate lcl_carrier` ). ENDTRY.
  8. Activate and test your global class as console app. Ensure that your code displays the new text on the console.

    1. Press Ctrl + F3.

    2. Press F9.

  9. In your global class, change the value of local constant c_carrier_id back to LH.

    1. Switch to the Global Class tab.

    2. Adjust the code as follows:

      Code Snippet
      Copy code
      Switch to dark mode
      12
      * CONSTANTS c_carrier_id TYPE /dmo/carrier_id VALUE 'UA'.
  10. Activate and test your global class as console app. Ensure that the code displays the carrier and flight details as before.

    1. Press Ctrl + F3.

    2. Press F9.

Log in to track your progress & complete quizzes