on 2024 Aug 02 5:54 PM
Hi,
We have a project running on CAP CDS7 which uses remote services in handlers like this
this.on('READ', 'Something', async req => {
const svc = await cds.connect.to('AnotherService');
const res = await svc.run(SELECT.from('RemoteThing', someId));
return res;
})
We are now trying to upgrade to CDS8 and all such delegated calls fail with errors like this:
Error during request to remote service: Failed to load destination. Caused by: No user token (JWT) has been provided. This is strictly necessary for 'OAuth2JWTBearer'.
Stepping through the remote requests we find that it fails in node_modules/@sap/cds/libx/_runtime/remote/Service.js. The authorization headers are no longer present in req.context.headers (only a single 'x-correlation-id' header remains there). The actual authorization header is in req.context.http.req.headers.authorization
// IMPORTANT: regular function is used on purpose, don't switch to arrow function.
this.on('*', async function on_handler(req, next) {
const { query } = req
if (!query && !(typeof req.path === 'string')) return next()
// early validation on first request for use case without remote API
// ideally, that's done on bootstrap of the remote service
if (typeof this.destination === 'object' && !this.destination.url)
throw new Error(`"url" or "destination" property must be configured in "credentials" of "${this.name}".`)
const reqOptions = getReqOptions(req, query, this)
reqOptions.headers = _setHeaders(reqOptions.headers, req)
const { kind, destination, destinationOptions } = this
const resolvedTarget = resolvedTargetOfQuery(query) || getTransition(req.target, this).target
const returnType = req._returnType
const additionalOptions = { destination, kind, resolvedTarget, returnType, destinationOptions }
// req.context.headers only contains 'x-correlation-id' after the upgrade, no jwt token is forwarded
// const jwt = req?.context?.headers?.authorization?.split(/^bearer /i)[1]
const jwt = req?.context?.http?.req?.headers?.authorization?.split(/^bearer /i)[1] // ---> Changing like this makes it work?
if (jwt) additionalOptions.jwt = jwt
// hidden compat flag in order to suppress logging response body of failed request
if (req._suppressRemoteResponseBody) {
additionalOptions.suppressRemoteResponseBody = req._suppressRemoteResponseBody
}
let result = await run(reqOptions, additionalOptions)
result = typeof query === 'object' && query.SELECT?.one && Array.isArray(result) ? result[0] : result
return result
})
Is there something we need to change in our application code with CDS8, or is this a bug? We tried for example making explicit "svc.tx(req).run(...)" which we have usually not had to do but that did not make any difference.
Thanks in advance for any advice!
//Carl
Hi @LuizGomes ,
We use a "patch-package" for now, with a patch file like that. Not a long term solution but works until we get this clarified.
diff --git a/node_modules/@sap/cds/libx/_runtime/remote/Service.js b/node_modules/@sap/cds/libx/_runtime/remote/Service.js
index 04e0929..a98bfcf 100644
--- a/node_modules/@sap/cds/libx/_runtime/remote/Service.js
+++ b/node_modules/@sap/cds/libx/_runtime/remote/Service.js
@@ -261,7 +261,7 @@ class RemoteService extends cds.Service {
const returnType = req._returnType
const additionalOptions = { destination, kind, resolvedTarget, returnType, destinationOptions }
- const jwt = req?.context?.headers?.authorization?.split(/^bearer /i)[1]
+ const jwt = req?.context?.headers?.authorization?.split(/^bearer /i)[1] || req?.context?.http?.req?.headers?.authorization?.split(/^bearer /i)[1]
if (jwt) additionalOptions.jwt = jwt
// hidden compat flag in order to suppress logging response body of failed request
Hope it helps
//Carl
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
68 | |
9 | |
8 | |
7 | |
7 | |
6 | |
6 | |
6 | |
5 | |
5 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.