From 17e1cd1d948be1d600371a38ddb4a66d404bfe62 Mon Sep 17 00:00:00 2001 From: D050513 Date: Tue, 3 Dec 2024 14:02:12 +0100 Subject: [PATCH 1/2] req.user vs req.user --- node.js/authentication.md | 28 +++++++++++++++------------- node.js/cds-serve.md | 4 ++-- node.js/events.md | 5 +++++ 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/node.js/authentication.md b/node.js/authentication.md index 253b2395c..93b2c3668 100644 --- a/node.js/authentication.md +++ b/node.js/authentication.md @@ -9,16 +9,16 @@ uacp: This page is linked from the Help Portal at https://help.sap.com/products/ # Authentication -{{$frontmatter?.synopsis}} This is done by [authentication middlewares](#strategies) setting the [`req.user` property](#cds-user) which is then used in [authorization enforcement](#enforcement) decisions. +{{$frontmatter?.synopsis}} This is done by [authentication middlewares](#strategies) setting the [`cds.context.user` property](#cds-user) which is then used in [authorization enforcement](#enforcement) decisions. [[toc]] ## cds. User { #cds-user .class } [user]: #cds-user -[`req.user`]: #cds-user +[`cds.context.user`]: #cds-user -Represents the currently logged-in user as filled into [`req.user`](events#user) by authentication middlewares. +Represents the currently logged-in user as filled into [`cds.context.user`](events#user) by authentication middlewares. Simply create instances of `cds.User` or of subclasses thereof in custom middlewares. For example: @@ -26,7 +26,7 @@ For example: const cds = require('@sap/cds') const DummyUser = new class extends cds.User { is:()=>true } module.exports = (req,res,next) => { - req.user = new DummyUser('dummy') + cds.context.user = new DummyUser('dummy') next() } ``` @@ -43,6 +43,8 @@ const yetAnotherUser = new cds.User({id: user.id, roles: user.roles, attr: user. ``` + + ### .is (\) {#user-is .method} Checks if user has assigned the given role. Example usage: @@ -112,7 +114,7 @@ By default, `cds.User.default` points to `cds.User.Anonymous`. However, you can ## Authorization Enforcement {#enforcement} -Applications can use the `req.user` APIs to do programmatic enforcement. +Applications can use the `cds.context.user` APIs to do programmatic enforcement. For example, the authorization of the following CDS service: ```cds @@ -132,7 +134,7 @@ can be programmatically enforced by means of the API as follows: const cds = require('@sap/cds') cds.serve ('CustomerService') .with (function(){ this.before ('*', req => - req.user.is('authenticated') || req.reject(403) + req.user.is('authenticated') || req.reject(403) ) this.before (['READ', 'CREATE'], 'Orders', req => req.user.is('admin') || req.reject(403) @@ -298,7 +300,7 @@ In contrast to [mocked authentication](#mocked), no default users are automatica This is the default strategy used in production. User identity, as well as assigned roles and user attributes, are provided at runtime, by a bound instance of the ['User Account and Authentication'](https://help.sap.com/products/BTP/65de2977205c403bbc107264b8eccf4b/419ae2ef1ddd49dca9eb65af2d67c6ec.html) service (UAA). This is done in form of a JWT token in the `Authorization` header of incoming HTTP requests. -This authentication strategy also adds [`req.user.tokenInfo`](#user-token-info). +This authentication strategy also adds [`cds.context.user.tokenInfo`](#user-token-info). **Prerequisites:** You need to add [@sap/xssec](https://help.sap.com/docs/HANA_CLOUD_DATABASE/b9902c314aef4afb8f7a29bf8c5b37b3/54513272339246049bf438a03a8095e4.html#loio54513272339246049bf438a03a8095e4__section_atx_2vt_vt) to your project: ```sh @@ -322,7 +324,7 @@ npm add @sap/xssec ### XSUAA-based Authentication { #xsuaa } -Authentication kind `xsuaa` is a logical extension of kind [`jwt`](#jwt) that additionally offers access to SAML attributes through `req.user.attr` (for example, `req.user.attr.familyName`). +Authentication kind `xsuaa` is a logical extension of kind [`jwt`](#jwt) that additionally offers access to SAML attributes through `cds.context.user.attr` (for example, `cds.context.user.attr.familyName`). **Prerequisites:** You need to add [@sap/xssec](https://help.sap.com/docs/HANA_CLOUD_DATABASE/b9902c314aef4afb8f7a29bf8c5b37b3/54513272339246049bf438a03a8095e4.html#loio54513272339246049bf438a03a8095e4__section_atx_2vt_vt) to your project: ```sh @@ -348,7 +350,7 @@ npm add @sap/xssec This is an additional authentication strategy using the [Identity Authentication Service](https://help.sap.com/docs/IDENTITY_AUTHENTICATION) (IAS) that can be used in production. User identity and user attributes are provided at runtime, by a bound instance of the IAS service. This is done in form of a JWT token in the `Authorization` header of incoming HTTP requests. -This authentication strategy also adds [`req.user.tokenInfo`](#user-token-info). +This authentication strategy also adds [`cds.context.user.tokenInfo`](#user-token-info). To allow forwarding to remote services, JWT tokens issued by IAS service don't contain authorization information. In particular, no scopes are included. Closing this gap is up to you as application developer. @@ -384,14 +386,14 @@ You can configure an own implementation by specifying an own `impl` as follows: Essentially, custom authentication middlewares must do two things: -First, they _must_ [fulfill the `req.user` contract](#cds-user) by assigning an instance of `cds.User` or a look-alike to the incoming request at `req.user`. +First, they _must_ [fulfill the `cds.context.user` contract](#cds-user) by assigning an instance of `cds.User` or a look-alike to the continuation of the incoming request at `cds.context.user`. -Second, if running in a multitenant environment, `req.tenant` must be set to a string identifying the tenant that is addressed by the incoming request. +Second, if running in a multitenant environment, `cds.context.tenant` must be set to a string identifying the tenant that is addressed by the incoming request. ```js module.exports = function custom_auth (req, res, next) { // do your custom authentication - req.user = new cds.User({ + cds.context.user = new cds.User({ id: '', roles: ['', ''], attr: { @@ -399,7 +401,7 @@ module.exports = function custom_auth (req, res, next) { : '' } }) - req.tenant = '' + cds.context.tenant = '' } ``` diff --git a/node.js/cds-serve.md b/node.js/cds-serve.md index 351ce9f32..abb234700 100644 --- a/node.js/cds-serve.md +++ b/node.js/cds-serve.md @@ -296,9 +296,9 @@ Be aware that overriding requires constant updates as new middlewares by the fra [Learn more about the middlewares default order.](#cds-middlewares){.learn-more} -#### Customization of `req.user` +#### Customization of `cds.context.user` -You can register middlewares to customize `req.user`. +You can register middlewares to customize `cds.context.user`. It must be done after authentication. If `cds.context.tenant` is manipulated as well, it must also be done before `cds.context.model` is set for the current request. diff --git a/node.js/events.md b/node.js/events.md index 10adc2207..294bf50dd 100644 --- a/node.js/events.md +++ b/node.js/events.md @@ -137,6 +137,11 @@ The current user, an instance of `cds.User` as identified and verified by the au [See reference docs for `cds.User`.](authentication#cds-user){.learn-more .indent} +::: tip +Please note the difference between `req` in a service handler (instance of `cds.EventContext`) and `req` in an express middleware (instance of `http.IncomingMessage`). +Case in point, `req.user` in a service handler is an official API and, if not explicitely set, points to `cds.context.user`. +On the other hand, setting `req.user` in a custom authentication middleware is deprecated. +::: From 8b16820a32249d473f62ca45232a6da64aad495b Mon Sep 17 00:00:00 2001 From: sjvans <30337871+sjvans@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:04:15 +0100 Subject: [PATCH 2/2] Update node.js/authentication.md --- node.js/authentication.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/node.js/authentication.md b/node.js/authentication.md index 93b2c3668..51213ebc1 100644 --- a/node.js/authentication.md +++ b/node.js/authentication.md @@ -43,8 +43,6 @@ const yetAnotherUser = new cds.User({id: user.id, roles: user.roles, attr: user. ``` - - ### .is (\) {#user-is .method} Checks if user has assigned the given role. Example usage: