Skip to content

Add help files to Authentication/Authorization queries #138

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Aug 14, 2024
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Default User is overwritten as privileged

Users that cannot be verified as authenticated are represented as `cds.User.default` internally. Setting this property to `cds.User.Privileged` may result in providing protected assets to unauthorized users.

## Recommendation

### Set up a development profile that uses non-production authentication

Overwriting `cds.User.default` as `cds.User.Privileged` for testing purposes is not recommended as such code may easily slip through production.

Instead, set up a development profile and opt in to use a non-production strategy such as `"basic"`, `"dummy"`, or `"mocked"` during its use. This can be done in the file `package.json` in the root folder of the CAP application:

``` json
{
"requires": {
"[dev]": {
"auth": "dummy"
}
}
}
```

Setting `"dummy"` as the development authentication strategy has the effect of disabling `@requires` and `@restrict` annotations of CDS definitions that provides authorization. The application during development then can be run and tested with the `--profile dev` option.

```shell
cds serve --profile dev
```

## Example

Setting `cds.User.default` to `cds.User.Privileged` may happen anywhere in the application. In the following example, the `server.js` file provides the top-level definition of a CAP application and overwrites the `default` user property with the `Privileged` class.

``` javascript
const cds = require("@sap/cds");
const app = require("express")();

/*
* Antipattern: `cds.User.default` is overwritten to `cds.User.Privileged`
*/
cds.User.default = cdsUser.Privileged;

cds.serve("all").in(app);
```

## References

- SAP CAPire Documentation: [cds.User.default](https://cap.cloud.sap/docs/node.js/authentication#default-user).
- SAP CAPire Documentation: [cds.User.Privileged](https://cap.cloud.sap/docs/node.js/authentication#privileged-user).
- SAP CAPire Documentation: [Authentication Strategies](https://cap.cloud.sap/docs/node.js/authentication#strategies).
- Common Weakness Enumeration: [CWE-250](https://cwe.mitre.org/data/definitions/250.html).
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# CAP Definitions Exposed without Access Controls

Although using a production-level authentication strategy such as `jwt` ensures that all entities and services require the user to be authenticated, this does not guarantee any further authorization. Furthermore, the lack of required authentication or authorization may imply a gap in the design of the system.

## Recommendation

### Use CDS-based authorization

CDL provides two annotations to declare access controls `@requires` and `@restrict` with the latter providing more granularity than the former. For example, to check if a request is being made by an authenticated user to the CDL entity or service, annotate it with `@requires: 'authenticated-user'`. On the other hand, if it needs to be read only via a certain group of users where the user has level greater than 2, use `@restrict: { grant: 'READ', to: 'SomeUser', where: { $user.level > 2 } }` (note the leading `$`).

#### Check the original CDS entity it is derived from

CDS entities may be derived from other entities by means of selection and projection. Derived definitions inherit access control conditions and optionally override them. In order to accurately determine what authorization an entity requires, the access control of the parent entity should be transitively inspected.

### Enforce authorization with JavaScript

Access control may be enforced when a request handler for the relevant entity or service is registered. Both `cds.Service.before` and `cds.Service.on` may be used for enforcement. For example, to restrict writing to and updating an entity to a user satisfying certain requirements, either one of the below handler registrations may be used:

``` javascript
/**
* Before serving a request to access SomeEntity, check if the request is coming from a user
* with SomeRole and level greater than 3.
*/
this.before(["WRITE", "UPDATE"], "SomeEntity", (req) => {
(req.user.is("SomeRole") && req.user.attr.level > 3) || req.reject(403);
});

/**
* On request to access SomeEntity, check if the request is coming from a user
* with SomeRole and level greater than 3.
*/
this.on(["WRITE", "UPDATE"], "SomeEntity", (req) => {
if (req.user.is("SomeRole") && req.user.attr.level > 3) {
/* Do something */
} else req.reject(403);
});
```

## Examples

The following CDS definition and its JavaScript implementation imposes no authorization on `SomeEntity`. Note that the `OriginalEntity` from which `DerivedEntity` derives from does not control the access either.

### db/schema.cds

``` cap-cds
namespace sample_namespace.sample_entities;

entity OriginalEntity {
Attribute1 : String(100);
Attribute2 : String(100)
}
```

### srv/service1.cds

``` cap-cds
using { sample_namespace.sample_entities as db_schema } from '../db/schema';

service SomeService {
entity DerivedEntity as projection on db_schema.OriginalEntity excluding { Attribute2 }
}
```

### srv/service1.js

``` javascript

const cds = require("@sap/cds");

module.exports = class Service1 extends cds.ApplicationService {
init() {
this.on("READ", "SomeService", (req) => { })
}
}
```

## References

- SAP CAPire Documentation: [Authorization Enforcement](https://cap.cloud.sap/docs/node.js/authentication#enforcement).
- SAP CAPire Documentation: [@restrict](https://cap.cloud.sap/docs/guides/security/authorization#restrict-annotation).
- SAP CAPire Documentation:
[@requires](https://cap.cloud.sap/docs/guides/security/authorization#requires).
- SAP CAPire Documentation: [Protecting Certain Entries](https://cap.cloud.sap/docs/cds/common#protecting-certain-entries).
- SAP CAPire Documentation: [Inheritance of Restrictions](https://cap.cloud.sap/docs/guides/security/authorization#inheritance-of-restrictions).
- SAP CAPire Documentation: [Authentication Enforced in Production](https://cap.cloud.sap/docs/node.js/authentication#authentication-enforced-in-production).
- Common Weakness Enumeration: [CWE-862](https://cwe.mitre.org/data/definitions/862.html).
- Common Weakness Enumeration: [CWE-306](https://cwe.mitre.org/data/definitions/306.html).
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Non-Production Authentication Strategy Used without Profiles

Using a non-production authentication strategy without setting up a distinct profile for development may pose allow unintended authentication and/or authorization if the application is deployed into production.

## Recommendation

### Isolate the use of development-level strategies to a development profile

Use separate profiles for development and deployment and select one as needed. In this way, properties including authentication strategies can be substituted by changing a single command line option: `--profile`. For example, having the following section in the application's `package.json` states that the `"dummy"` authentication strategy must be used while `"xsuaa"`, a production-grade strategy, should be used when deployed:

``` json
{
"requires": {
"[dev]": {
"auth": "dummy"
},
"[deploy]": {
"auth": "xsuaa"
}
}
}
```

The application can be now run in different modes depending on the `--profile` command line option:

``` shell
$ cds serve --profile dev # Runs the application in development profile with strategy "dummy"
$ cds serve --profile deploy # Runs the application in development profile with strategy "xsuaa"
```

## Example

The following CAP application states that it uses `"basic"` authentication strategy along with mocked credentials. Using the pair of username and password, an attacker can gain access to certain assets by signing in to the application.

``` json
{
"cds": {
"requires": {
"auth": {
"kind": "basic",
"users": {
"JohnDoe": {
"password": "JohnDoesPassword",
"roles": ["JohnDoesRole"],
"attr": {}
},
"JaneDoe": {
"password": "JaneDoesPassword",
"roles": ["JaneDoesRole"],
"attr": {}
}
}
}
}
}
}
```

## References

- Common Weakness Enumeration: [CWE-288](https://cwe.mitre.org/data/definitions/288.html).
- Common Weakness Enumeration: [CWE-798](https://cwe.mitre.org/data/definitions/798.html).
- SAP CAPire Documentation: [Authentication Strategies](https://cap.cloud.sap/docs/node.js/authentication#strategies).
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bad-authn-authz/EntityExposedWithoutAuthn.ql
bad-authn-authz/EntityExposedWithoutAuthn/EntityExposedWithoutAuthn.ql
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bad-authn-authz/EntityExposedWithoutAuthn.ql
bad-authn-authz/EntityExposedWithoutAuthn/EntityExposedWithoutAuthn.ql
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bad-authn-authz/EntityExposedWithoutAuthn.ql
bad-authn-authz/EntityExposedWithoutAuthn/EntityExposedWithoutAuthn.ql
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bad-authn-authz/EntityExposedWithoutAuthn.ql
bad-authn-authz/EntityExposedWithoutAuthn/EntityExposedWithoutAuthn.ql
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bad-authn-authz/DefaultUserIsPrivileged.ql
bad-authn-authz/DefaultUserIsPrivileged/DefaultUserIsPrivileged.ql
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bad-authn-authz/NonProductionStrategyUsed.ql
bad-authn-authz/NonProductionStrategyUsed/NonProductionStrategyUsed.ql
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bad-authn-authz/NonProductionStrategyUsed.ql
bad-authn-authz/NonProductionStrategyUsed/NonProductionStrategyUsed.ql
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bad-authn-authz/NonProductionStrategyUsed.ql
bad-authn-authz/NonProductionStrategyUsed/NonProductionStrategyUsed.ql