Controlling Access to Data

Objective

After completing this lesson, you will be able to restrict access to resources by means of annotations

Restrictions

Authentication and Authorization

With regard to application security, the concepts of authentication and authorization play a crucial role.

Watch the video to get an overview of authentication and authorization.

We have not yet configured any authorizations in our application. This means that there are currently no restrictions and all requests still have full access to the entire application. In this lesson, we will learn how to restrict access to the application.

In a productive environment, all endpoints are authenticated by default, even if no restrictions are configured. The authentication method is freely customizable. For convenience, a set of authentication methods is supported out-of-the-box to cover most common scenarios. In case it is required for business reasons to expose open endpoints to anonymous users, additional measures must be taken. Configuring authentication for the production environment is not covered in this course.

As we have already seen, no authentication is required when testing the application in the development environment. We will see later how to configure authentication for the test environment.

Separation of Concerns

In the following, we will explore annotations that you can use to control access to business data at a fine-grained level. You can insert the discussed annotations directly into the .cds files in which the services are defined. In our case, this would be the file cat-service.cds for the CatalogService and the file admin-service.cds for the AdminService.

However, it is best practice to store the authorization annotations in different .cds files in order to separate them from the actual service definition. This keeps the actual service definitions concise and focused on structure only. It also allows you to give authorization models separate ownership and lifecycle.

We will follow this best practice and create separate .cds files to model the access rules for the CatalogService and the AdminService. We call these files cat-service-auth.cds and admin-service-auth.cds respectively and save them in the srv folder of our project, just like the files with the service definitions.

Note

The annotations we will use make the runtime automatically enforce proper access control. If this generic enforcement does not meet your needs, you can also implement a custom programmatic enforcement by means of an authorization enforcement API.

@readonly and @requires

First, let's take a look at the cat-service-auth.cds file, which we use to control access to the CatalogService (see following figure).

In this file, we import the definitions of the Authors and Books entities as well as the definition of the submitOrder action from the CatalogService model via the using directive.

The Authors and the Books entity are annotated with @readonly via the annotate directive in order to restrict access for all users to read-only access.

Note

In addition to the @readonly annotation, there is also an @insertonly annotation. Both annotations introduce access control at entity level.

As a basis for access control, you can design conceptual roles that are application-specific. Users can have multiple roles that are assigned by an administrative user in the platform's authorization management solution.

In addition to the application-specific user roles, CAP also supports some predefined so-called pseudo roles, such as authenticated-user. This role refers to users who have been successfully authenticated.

In the example shown, the @requires annotation is used to control that only authenticated users may execute the submitOrder action.

Note

The @requires annotation can be used at service level, entity level and action/function level to control access accordingly.

@restrict

Next, let's take a look at the admin-service-auth.cds file, which contains the access control for the AdminService (see following figure).

Here, too, we first employ the using directive to import the definitions to be annotated (Authors and Books Entity) from the AdminService model.

The Authors entity is annotated with @(requires: 'admin'). This determines that only users who have the application-specific admin role can access the Authors entity.

To define authorizations for the Books entity, the @restrict annotation is used. It specifies that only users with the application-specific admin role are allowed to perform READ, CREATE and UPDATE operations on the Books entity. DELETE operations are also only permitted for users with the admin role, with the additional restriction that only books with a stock of 0 may be deleted.

The @restrict annotation provides an array with any number of privilege objects, whereby each privilege object has the following structure:

Code Snippet
1
{ grant: <events>, to: <roles>, where: <filter-condition> }

The properties of the privilege object are defined as follows:

  • grant

    one or more events (such as READ, CREATE, UPDATE, and DELETE) that the privilege applies to

  • to

    one or more user roles or pseudo roles that the privilege applies to (optional)

  • where

    a filter condition that further restricts access on an instance level (optional)

A request passes a restriction consisting of an array of privileges if at least one of the privileges is met.

Note

The @restrict annotation can be used at service level, entity level and action/function level to define authorizations. However, the grant and where properties are only supported for entities and not for services and actions/functions.

Note

Annotations such as @requires or @readonly are just convenience shortcuts for @restrict, for example:

  • @(requires: 'admin') is equivalent to @(restrict: [ { grant: '*', to: 'admin' } ])
  • @readonly is the same as @(restrict: [ { grant: 'READ' } ])

Authentication

Authentication Strategies

Now that we have seen how to define authorizations with the help of annotations, we want to look at authentication next. The successful authentication of a user forms the basis for being able to carry out authorization checks.

CAP ships with a number of prebuilt authentication strategies.

In production, the jwt authentication strategy is used by default. The user identity as well as the assigned roles and user attributes are provided at runtime by a bound instance of the User Account and Authentication (UAA) service. This is done in the form of a JWT token in the Authorization header of incoming HTTP requests.

During development, the authentication strategy mocked is used by default. This authentication strategy uses basic authentication with predefined mock users. Optionally, you can define additional users via the package.json file as shown in the following figure:

Note

To check the current configuration with regard to authentication, execute the following command in the project root in the terminal:

Code snippet
cds env get requires.auth
Expand

For the configuration shown in the figure, the output contains, among other things, a list of available users. In addition to the predefined users such as alice or bob, the list also contains the additionally configured users adminuser and catuser. Both users have the password abcd1234. While the catuser has no application-specific role, the adminuser is assigned the admin role.

Testing

The mocked authentication uses basic authentication. You can therefore use the Authorization header with the Basic authentication scheme in your requests for testing purposes. The credentials are specified in the form <user>:<password>, as shown in the following example:

Code Snippet
12
GET <service_url>/Books Authorization: Basic catuser:abcd1234

Demonstration & Exercise: Add Restrictions to the CDS Model

Note

As exercise, carry out the step-by-step instructions in the following demonstration yourself in the SAP Business Application Studio.

As a starting point for the exercise, use the outcome of the previous exercise Use Localized Error Messages if you have successfully completed it. Alternatively, you can also use the branch 15_error_messages from the following GitHub repository as a starting point:

https://github.com/SAP-samples/cap-development-learning-journey

The complete implementation of the simulation can be found in the 16_access_control branch of the GitHub repository.

Detailed information on the content of the repository and how to use it can be found here.

Watch the video to see how to add restrictions to the CDS model.

Log in to track your progress & complete quizzes