Skip to content

Commit 03e6aa4

Browse files
beckermarcsmahati
andauthored
Improve explanations around custom Spring Security configurations (#2111)
Co-authored-by: Mahati Shankar <[email protected]>
1 parent 47971d9 commit 03e6aa4

File tree

1 file changed

+19
-17
lines changed

1 file changed

+19
-17
lines changed

java/security.md

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -42,15 +42,15 @@ Without security configured, CDS services are exposed to public. Proper configur
4242

4343
## Authentication { #authentication}
4444

45-
Authentication rejects user requests with invalid authentication and limits the possible resource impact.
45+
Authentication rejects user requests with invalid authentication and limits the possible resource impact.
4646

4747
Rejecting them as soon as possible is one of the reasons why it's not an integral part of the CAP runtime and needs to be configured on the application framework level. In addition, CAP Java is based on a [modular architecture](./developing-applications/building#modular_architecture) and allows flexible configuration of any authentication method.
4848
By default, it supports the standard BTP platform identity services [out of the box](#xsuaa-ias):
4949

5050
- [SAP Cloud Identity Services Identity Authentication (IAS)](https://help.sap.com/docs/cloud-identity-services) - preferred solution integrating endpoints cross SAP-systems
5151
- [SAP Authorization and Trust Management Service (XSUAA)](https://help.sap.com/docs/authorization-and-trust-management-service) - previous offering scoped to a BTP landscape
5252

53-
Which are highly recommended for production usage. For specific use cases, [custom authentication](#custom-authentication) can be configured as well.
53+
Which are highly recommended for production usage. For specific use cases, [custom authentication](#custom-authentication) can be configured as well.
5454
Local development and testing can be done easily with built-in [mock user](#mock-users) support.
5555

5656
### Configure XSUAA and IAS Authentication { #xsuaa-ias}
@@ -164,7 +164,10 @@ Please note that the authentication mode has no impact on the *authorization* be
164164

165165
#### Customizing Spring Boot Security Configuration { #custom-spring-security-config}
166166

167-
If you want to explicitly change the automatic security configuration, you can add an _additional_ Spring security configuration on top that overrides the default configuration by CAP. This can be useful, for instance, if an alternative authentication method is required for *specific endpoints* of your application.
167+
If you want to explicitly change the automatic security configuration, you can add an _additional_ Spring security configuration on top that overrides the default configuration by CAP.
168+
This can be useful, for instance, if an alternative authentication method is required for *specific endpoints* of your application.
169+
170+
As the default security configurations provided by CAP act as the last line of defense and handle any request by default, you need to ensure that your custom security configurations have higher precedence. At the `SecurityFilterChain` bean method, set the `@Order` annotation with a lower numeric value, for example `1`:
168171

169172
```java
170173
@Configuration
@@ -184,9 +187,6 @@ public class AppSecurityConfig {
184187
}
185188
```
186189
Due to the custom configuration, all URLs matching `/public/**` are opened for public access.
187-
::: tip
188-
The Spring `SecurityFilterChain` requires CAP Java SDK [1.27.x](../releases/archive/2022/aug22#minimum-spring-boot-version-2-7-x) or later. Older versions need to use the deprecated `WebSecurityConfigurerAdapter`.
189-
:::
190190

191191
::: warning _❗ Warning_ <!-- -->
192192
Be cautious with the configuration of the `HttpSecurity` instance in your custom configuration. Make sure that only the intended endpoints are affected.
@@ -201,7 +201,7 @@ public class ActuatorSecurityConfig {
201201

202202
@Bean
203203
@Order(1)
204-
public SecurityFilterChain actuatorFilterChain(HttpSecurity http)
204+
public SecurityFilterChain actuatorFilterChain(HttpSecurity http)
205205
throws Exception {
206206
return http
207207
.securityMatcher(AntPathRequestMatcher.antMatcher("/actuator/**"))
@@ -214,6 +214,8 @@ public class ActuatorSecurityConfig {
214214
}
215215
```
216216

217+
In case you want to write your own custom security configuration that acts as a last line of defense and handles any request you need to disable the CAP security configurations by setting <Config java>cds.security.authentication.authConfig.enabled: false</Config>, as Spring Security forbids registering multiple security configurations with an any request security matcher.
218+
217219
### Custom Authentication { #custom-authentication}
218220

219221
You're free to configure any authentication method according to your needs. CAP isn't bound to any specific authentication method or user representation such as introduced with XSUAA, it rather runs the requests based on a [user abstraction](../guides/security/authorization#user-claims). The CAP user of a request is represented by a [UserInfo](https://www.javadoc.io/doc/com.sap.cds/cds-services-api/latest/com/sap/cds/services/request/UserInfo.html) object that can be retrieved from the [RequestContext](https://www.javadoc.io/doc/com.sap.cds/cds-services-api/latest/com/sap/cds/services/request/RequestContext.html) as explained in [Enforcement API & Custom Handlers](#enforcement-api).
@@ -238,7 +240,7 @@ public class CustomUserInfoProvider implements UserInfoProvider {
238240
}
239241
}
240242
if (userInfo != null) {
241-
/* any modification of the resolved user goes here: */
243+
/* any modification of the resolved user goes here: */
242244
XsuaaUserInfo xsuaaUserInfo = userInfo.as(XsuaaUserInfo.class);
243245
userInfo.setName(xsuaaUserInfo.getEmail() + "/" +
244246
xsuaaUserInfo.getOrigin()); // normalizes name
@@ -625,7 +627,7 @@ In addition to standard authorization, CAP Java provides additional out of the b
625627

626628
### Deep Authorization { #deep-auth}
627629

628-
Queries to Application Services are not only authorized by the target entity which has a `@restrict` or `@requires` annotation, but also for all __associated entities__ that are used in the statement.
630+
Queries to Application Services are not only authorized by the target entity which has a `@restrict` or `@requires` annotation, but also for all __associated entities__ that are used in the statement.
629631
__Compositions__ are neither checked nor extended with additional filters.
630632
For instance, consider the following model:
631633

@@ -643,15 +645,15 @@ entity Orders {
643645
}
644646
```
645647

646-
For the following OData request `GET Orders(ID='1')/items?$expand=book`, authorizations for `Orders` and for `Books` are checked.
647-
If the entity `Books` has a `where` clause for [instance-based authorization](/java/security#instance-based-auth),
648+
For the following OData request `GET Orders(ID='1')/items?$expand=book`, authorizations for `Orders` and for `Books` are checked.
649+
If the entity `Books` has a `where` clause for [instance-based authorization](/java/security#instance-based-auth),
648650
it will be added as a filter to the sub-request with the expand.
649651

650-
Custom CQL statements submitted to the [Application Service](/java/cqn-services/application-services) instances
652+
Custom CQL statements submitted to the [Application Service](/java/cqn-services/application-services) instances
651653
are also authorized by the same rules including the path expressions and subqueries used in them.
652654

653-
For example, the following statement checks role-based authorizations for both `Orders` and `Books`,
654-
because the association to `Books` is used in the select list.
655+
For example, the following statement checks role-based authorizations for both `Orders` and `Books`,
656+
because the association to `Books` is used in the select list.
655657

656658
```java
657659
Select.from(Orders_.class,
@@ -675,15 +677,15 @@ Be careful when you modify or extend the statements in custom handlers.
675677
Make sure you keep the filters for authorization.
676678
:::
677679

678-
Starting with CAP Java `4.0`, deep authorization is on by default.
680+
Starting with CAP Java `4.0`, deep authorization is on by default.
679681
It can be disabled by setting <Config java>cds.security.authorization.deep.enabled: false</Config>.
680682

681683
[Learn more about `@restrict.where` in the instance-based authorization guide.](/guides/security/authorization#instance-based-auth){.learn-more}
682684

683685
### Forbidden on Rejected Entity Selection { #reject-403 }
684686

685-
Entities that have an instance-based authorization condition, that is [`@restrict.where`](/guides/security/authorization#restrict-annotation),
686-
are guarded by the CAP Java runtime by adding a filter condition to the DB query **excluding not matching instances from the result**.
687+
Entities that have an instance-based authorization condition, that is [`@restrict.where`](/guides/security/authorization#restrict-annotation),
688+
are guarded by the CAP Java runtime by adding a filter condition to the DB query **excluding not matching instances from the result**.
687689
Hence, if the user isn't authorized to query an entity, requests targeting a *single* entity return *404 - Not Found* response and not *403 - Forbidden*.
688690

689691
To allow the UI to distinguish between *not found* and *forbidden*, CAP Java can detect this situation and rejects`PATCH` and `DELETE` requests to single entities with forbidden accordingly.

0 commit comments

Comments
 (0)