Skip to content

Commit 806d534

Browse files
committed
auth, local url
1 parent 96f55b6 commit 806d534

File tree

7 files changed

+74
-64
lines changed

7 files changed

+74
-64
lines changed

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
99

1010
### Fixed
1111

12-
- For local development, authentication is skipped for authentication kind `mocked`
13-
- First mocked user (of `cds.requires.auth.users`) is taken as authenticated user for websocket connection (e.g. `alice`)
12+
- Authentication is skipped for kind `mocked` and `basic` for local development
13+
- Anonymous user or first user of `cds.requires.auth.users` (i.e. `alice`) when not set
14+
- Supports relative paths for `WebSocketBaseURL` for local development
1415

1516
## Version 1.9.4 - 2026-02-03
1617

README.md

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -433,10 +433,20 @@ Example for xsuaa based CDS auth strategy:
433433

434434
Headers of Websocket Upgrade request can be accessed via `req.http.req.headers` in websocket service handlers.
435435

436-
#### Local Development Authorization
436+
#### Local Development
437437

438-
For local development, authentication is skipped for authentication kind `mocked`. First mocked user (of `cds.requires.auth.users`)
439-
is taken as authenticated user for websocket connection (e.g. `alice`) in local development setup.
438+
For local development, authentication is skipped for authentication kind `mocked` and `basic`.
439+
If login is required (`cds.requires.auth.login_required: true`), first mocked user (see `cds.requires.auth.users`)
440+
is taken as authenticated user for websocket connection (e.g. `alice`),
441+
otherwise the websocket connection is established with an anonymous user.
442+
443+
Using authentication kind `basic` or `cds.requires.auth.login_required: true` is not recommended for local development,
444+
as the websocket connection is established via WebSocket Upgrade request, which does not support interactive login.
445+
Nevertheless, it could be simulated by hardcoding an authentication cookie in browser as follows:
446+
447+
```js
448+
document.cookie = "X-Authorization=Basic YWxpY2U6YWxpY2U; path=/"; // mock auth for alice
449+
```
440450

441451
### Invocation Context
442452

@@ -1234,19 +1244,23 @@ Modeled action parameters `context`, `exit` and `reset` are mapped from `pcp` me
12341244
#### Event-Driven Side Effects
12351245
12361246
PCP format can be used to emit Fiori Elements Event-Driven Side Effects via WebSocket events.
1247+
Websocket kind `ws` must be configured (default), as UI5 only supports WebSocket protocol for Fiori Elements side effects.
12371248
12381249
First OData V4 service metadata is extended for side effects to automatically connect to the corresponding websocket endpoint and channel:
12391250
12401251
```cds
12411252
@Common : {
1242-
WebSocketBaseURL : '/ws/fiori',
1253+
WebSocketBaseURL : 'ws/fiori',
12431254
WebSocketChannel #sideEffects: 'sideeffects'
12441255
}
12451256
service FioriService {
12461257
...
12471258
}
12481259
```
12491260
1261+
Path of `WebSocketBaseURL` shall be defined relatively (i.e. no leading slash) to the OData service URL,
1262+
to be correctly resolved in Fiori Elements, especially in context of WorkZone.
1263+
12501264
Event-driven side effects are configured in PCP format enabled service via the following annotations:
12511265
12521266
- **Event level**:
@@ -1271,7 +1285,7 @@ Example:
12711285
12721286
```cds
12731287
@Common: {
1274-
WebSocketBaseURL: '/ws/fiori',
1288+
WebSocketBaseURL: 'ws/fiori',
12751289
WebSocketChannel #sideEffects: 'sideeffects',
12761290
}
12771291
service FioriService {

package-lock.json

Lines changed: 39 additions & 49 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,10 @@
5656
"@sap/cds": "^9.7.1",
5757
"@sap/cds-dk": "^9.7.0",
5858
"@socket.io/redis-adapter": "^8.3.0",
59-
"@socket.io/redis-streams-adapter": "^0.2.3",
59+
"@socket.io/redis-streams-adapter": "^0.3.0",
6060
"eslint": "^9.39.2",
6161
"eslint-config-prettier": "^10.1.8",
62-
"eslint-plugin-jest": "^29.12.2",
62+
"eslint-plugin-jest": "^29.13.0",
6363
"eslint-plugin-n": "^17.23.2",
6464
"globals": "^17.3.0",
6565
"jest": "^30.2.0",

src/socket/base.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -443,13 +443,14 @@ class SocketServer {
443443
!restrict_all ||
444444
cds.context?.user?._is_privileged ||
445445
!cds.context?.user?._is_anonymous ||
446-
cds.env.requires?.auth.kind === "mocked"
446+
["mocked", "basic"].includes(cds.env.requires?.auth.kind)
447447
) {
448-
if (cds.env.requires?.auth.kind === "mocked") {
449-
const mockedUsers = Object.values(cds.env.requires?.auth?.users || {});
450-
if (mockedUsers.length) {
451-
req.user ??= new cds.User(mockedUsers[0]);
448+
if (cds.context && !cds.context.user) {
449+
const users = Object.values(cds.env.requires?.auth?.users || {});
450+
if (cds.env.requires?.auth?.login_required && users.length) {
451+
cds.context.user = new cds.User(users[0]);
452452
}
453+
cds.context.user ??= new cds.User.Anonymous();
453454
}
454455
return next();
455456
}

src/socket/ws.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ class SocketWSServer extends SocketServer {
3939
request.queryOptions = urlObj?.query || {};
4040
request.id ??= request.queryOptions.id;
4141
request.url = urlObj?.pathname;
42+
if (!this.services.get(request.url)) {
43+
// Route webapp relative requests (local)
44+
request.url = request.url.replace(/\/.*\/webapp(\/.*)/, "$1");
45+
}
4246
if (!(typeof this.services.get(request.url) === "function")) {
4347
socket.write(`HTTP/1.1 404 Not Found\r\n\r\n`);
4448
socket.destroy();

test/_env/srv/fiori.cds

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
using {sap.capire.bookshop as my} from '../db/bookshop';
22

33
@Common: {
4-
WebSocketBaseURL: '/ws/fiori',
4+
WebSocketBaseURL: 'ws/fiori',
55
WebSocketChannel #sideEffects: 'sideeffects',
66
}
77
service FioriService {

0 commit comments

Comments
 (0)