Is it possible to retrieve subscriber destination using IAS JWT token?
I am following this documentation to retrieve the destinations. Currently I have destinations defined in the provider instance binding.
Our's is an IAS based reuse service and we do not use XSUAA. We want to use destination service to call the tenant specific API on a consumer app which is subscribed from a subscriber account. Such destinations from the service bindings of our reuse services are working fine whereas by using the IAS JWT token, the SDK is not able to fetch the destination from the subscriber tenant and prints following error:
2024-01-22T16:01:22.87+0530 [APP/PROC/WEB/0] OUT {"custom_fields":{"messageContext":"register-destination","package":"connectivity"},"level":"error","logger":"sap-cloud-sdk-logger","message":"Could neither determine tenant from JWT nor service binding to XSUAA, although a JWT was passed. Destination will be registered without tenant information.","msg":"Could neither determine tenant from JWT nor service binding to XSUAA, although a JWT was passed. Destination will be registered without tenant information.","timestamp":"2024-01-22T10:31:22.879Z","written_at":"2024-01-22T10:31:22.879Z","written_ts":1705919482879}
2024-01-22T16:01:22.88+0530 [APP/PROC/WEB/0] OUT Error: Error: Could not find binding to the XSUAA service.
Is there a way to overcome this issue and get the destination from subscriber account? Kindly suggest.
Versions in use:
"@sap-cloud-sdk/connectivity": "^3.8.1"
"@sap-cloud-sdk/http-client": "^3.8.1"
I tried binding the XSUAA instance and after that I am getting 401 error while fetching the destination. When I tried to generate token manually for destination service, below is the error I am getting.
Hi @preekmr-sap ,
could you share a snippet of the code that triggers this error?
@mr-flannery Sure. I am trying to get the destination using the following snippet where I am passing IAS issues JWT token.
public async getDestination(): Promise<Destination> {
try {
const destination = await getDestination({
destinationName: this.destinationName,
jwt: this.jwt,
selectionStrategy: subscriberFirst,
})
if (!destination) {
throw new Error(`Destination "${this.destinationName}" not found. Please check your destination configuration.`);
}
return destination
} catch (error: unknown) {
console.log('Error:', error);
throw new Error(`Failed to fetch destination: ${this.destinationName}`);
}
}
cURL command that gives the issuer error:
curl --location 'https://forms-prod-eu10.authentication.eu10.hana.ondemand.com/oauth/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer' \
--data-urlencode 'response_type=token' \
--data-urlencode 'client_id=sb-forms-ext-dev-eu10!b149375' \
--data-urlencode 'app_tid=cd24e352-ef98-46d7-bfc3-cbf4e779b3b6' \
--data-urlencode 'client_secret=3quRxBkb9fcu6rKcg3wy9ce5t7A=' \
--data-urlencode 'assertion=eyJraWQiOiJFWkpjUzRrSVBKVDVlQTBPbGsyU280Y2h4MVUiLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiI2M2E3NWI3NC0wNzdhLTQyYjEtOWVhYy1iNGY3Njc1NzJjNTgiLCJhcHBfdGlkIjoiY2QyNGUzNTItZWY5OC00NmQ3LWJmYzMtY2JmNGU3NzliM2I2IiwiaXNzIjoiaHR0cHM6Ly9mb3JtczMuYWNjb3VudHMub25kZW1hbmQuY29tIiwiZ2l2ZW5fbmFtZSI6IkNoYWQiLCJpYXNfaXNzIjoiaHR0cHM6Ly9mb3JtczMuYWNjb3VudHMub25kZW1hbmQuY29tIiwiYXVkIjpbIjY0NTIxMmQ1LWViZjgtNDI3Zi1iMmJmLWJmZDk1NzI5YzlkMCIsIjcwMDAwMTMyLTNmNzEtNDA5NC04NjU5LWMzODZjNTdiMmJkOSIsImJjZjY0ZGM4LWMwODMtNDkyMy1hNThiLWEwYjZjNWRlZDVhYiJdLCJzY2ltX2lkIjoiNjNhNzViNzQtMDc3YS00MmIxLTllYWMtYjRmNzY3NTcyYzU4IiwidXNlcl91dWlkIjoiNjNhNzViNzQtMDc3YS00MmIxLTllYWMtYjRmNzY3NTcyYzU4IiwiYXpwIjoiNzAwMDAxMzItM2Y3MS00MDk0LTg2NTktYzM4NmM1N2IyYmQ5Iiwiem9uZV91dWlkIjoiY2QyNGUzNTItZWY5OC00NmQ3LWJmYzMtY2JmNGU3NzliM2I2IiwiY25mIjp7Ing1dCNTMjU2IjoiZjNfNXp6YU5udjhONjl5NkVMVUxCcXlFcDhGZTZVaUctOEVOYWpTNzJUayJ9LCJleHAiOjE3MDU5Mzc0OTIsImlhdCI6MTcwNTkzMzg5MiwiZmFtaWx5X25hbWUiOiJOb2xsIiwianRpIjoiYmUzMTBkNzctZWYyMi00Njk4LTk2ZTMtYzFjYzIzN2MyMWE0IiwiZW1haWwiOiJjbm9sbEBhcmliYS5jb20ifQ.efSy-VpI2S6jlvZ7vphq55Upxrcu4Ekw8RyBqk5amLDds0UYj0OYBcQhMmQ7PxDUKQD6XW-DZQ8GlstIqRRAfh9Q6FqDWnvMqJC_QBVfS7RshUVF8eOzAvRaQh0IKpkjw-FGeHwgaBytBqwBEoFeo6_e358K4JT3OYcSy6VmT69TSkcIqei-mgBdc8vgW5-RcsgS1OqEOp_ivOBVhAud6SVQLdrSZGk3Wd2LclzmQWidGi6GfAyZmxV0C3laNO41obGJ89BLRLPswK2NP6pW2emQEuL1-5sVpunH5MZc3bCGiGMmMg3PjIjzXvI7e5tyfWV1l-mQ-ja3gMJPzf_JFg'
Could you try adding iasToXsuaaTokenExchange: false as additional property to the object passed to getDestination?
@mr-flannery It resolved the error. But I am not able to access the destination in the subscriber account. If the destination is present in provider destination service instance, then it works. Any thing we can do to access the destination that is present in the subscriber tenant?
2024-01-22T22:03:04.42+0530 [APP/PROC/WEB/0] OUT {"custom_fields":{"messageContext":"register-destination","package":"connectivity"},"level":"error","logger":"sap-cloud-sdk-logger","message":"Could neither determine tenant from JWT nor service binding to XSUAA, although a JWT was passed. Destination will be registered without tenant information.","msg":"Could neither determine tenant from JWT nor service binding to XSUAA, although a JWT was passed. Destination will be registered without tenant information.","timestamp":"2024-01-22T16:33:04.429Z","written_at":"2024-01-22T16:33:04.429Z","written_ts":1705941184429}
2024-01-22T22:03:04.47+0530 [APP/PROC/WEB/0] OUT Error: Error: Destination "DemoApp" not found. Please check your destination configuration.
2024-01-22T22:03:04.47+0530 [APP/PROC/WEB/0] OUT at DestinationService.<anonymous> (/home/vcap/app/srv/service/destination.service.js:30:27)
2024-01-22T22:03:04.47+0530 [APP/PROC/WEB/0] OUT at Generator.next (<anonymous>)
2024-01-22T22:03:04.47+0530 [APP/PROC/WEB/0] OUT at fulfilled (/home/vcap/app/srv/service/destination.service.js:5:58)
2024-01-22T22:03:04.47+0530 [APP/PROC/WEB/0] OUT at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Hi @mr-flannery I think we need iasToXsuaaTokenExchange to be true since we can send only IAS based JWT to lookup since our service is an IAS based one. I do not see logic inside cloud-sdk-js library source to read tenant from zone_uuid instead of zid, so I am assuming exchange of IAS token to XSUAA token is necessary. But if I bind my service to XSUAA instance, I am getting error as mentioned in my first comment.
I think the problem is that we are forwarding the same IAS token from the app -> reuse service -> getDestination method. That could be the reason why getDestination fails with 401 while generating the token for destination service.
Kindly advise on how to proceed since this is a blocker for us. Thanks!
Hi @preekmr-sap , in theory, you should not need to the token exchange, at least as far as I'm aware. Why this doesn't work in the Cloud SDK we must investigate. We will get back to you as soon as we have reproduced the issue or produced a working setup.
Can you give us some more insights on how users are calling your service, especially what kind of token is used?
Hi @preekmr-sap , in theory, you should not need to the token exchange, at least as far as I'm aware. Why this doesn't work in the Cloud SDK we must investigate. We will get back to you as soon as we have reproduced the issue or produced a working setup.
Can you give us some more insights on how users are calling your service, especially what kind of token is used?
Thanks @mr-flannery. Consumer apps will be calling our service using IAS JWT token. They may use client_credentials or password grant types to generate the token. Currently the consumers of our services are hosted with DwC, hence the consumer application would have IAS JWT token in their runtime and they would be passing along the same token for our reuse service. Consumer Apps have declared our reuse service as their dependency in their IAS binding using consumed-services parameter.
Please do let me know if you need further information. Thanks!
@preekmr-sap so I talked to a colleague and a few things are clearer to me. I still need to validate, but here's what I understood now:
- The destination service does not accept IAS tokens, so when using the JS SDK, you need to exchange the IAS token for a XSUAA token. The SDK will do this for you if there is an XSUAA binding (and apparently throw an error if there is none 🙃 )
- For the destination service to accept your call, it must have been informed during tenant onboarding that the subscribing tenant should also be subscribed to the destination service. So depending on your concrete setup, this might be an issue.
The last time I looked into such scenarios, SMS and Zones were still a thing. I'm afraid I'm not up to date as to what services are currently used for such a scenario. Could you give me an overview of what service(s) you're using to implement the tenant lifecycle and subscription callbacks?
Also, could you please send me a link to your repository? You'll find my name on my Github profile, and then you'll have my SAP address :)
Hi @mr-flannery , As you are aware I have explored further. If I use the client_id and client_secret from the destination service binding for XSUAA token exchange, it works! But the cloud-sdk-js library uses client id and secret from the XSUAA instance that the running application is bound to, hence the error "Bad Credentials" is thrown.
Hi @preekmr-sap ,
With version 4.1.0 of the Cloud SDK, we removed the reliance on XSUAA binding while retrieving destinations.
With that your use case must work now. Could you please test this out?
Regards, Kavitha