Personal Insights
User Propagation between SAP BTP and third-party Applications.
|
This brief is to demonstrate how one could access a backend micro-service deployed on SAP BTP and protected by an SAP app-router [native] application from a non-BTP [foreign] application. Actually it seems to be a fairly common scenario. Some business users may be flocking directly into BTP, but some others may have already been authenticated upfront and elsewhere but still need to access backend services hosted on BTP without being forced to re-authenticate. So the question is how to ensure a seamless user identity propagation for users coming into BTP from a foreign context? Let’s focus on some basic facts and assumptions:
Pre-requisites:
Good to know:
Disclaimer:
|
Putting it all together
The basic build components are as follows:
Please refer to appendix and gists for further details on the application structure and build.
An IDP-initiated flow.
We want to be able to gain access to resources (micro-services) hosted on BTP without being redirected to a BTP login page when calling into these resources from a context of a foreign application.
When it comes to user authentication and user SSO there are two basic flows:
- the interactive, SP-initiated flow (SAML Web SSO)
- the unmanned, IDP-initiated flow.
The IDP-initiated authentication (user SSO) and user authorisations between an application and a micro-service is well documented here in the chapter User Propagation between Cloud Foundry Applications
Thus the only twist is that our application is a non-BTP one.
To summarise, all we need is an instance of an OAuth2SAMLBearerAssertion destination that combines a user identity propagation [via an IDP-initiated SAML SSO flow] with user scopes (authorisations) checks against an OAuth2 service provider.
In order to create such a destination definition we need to have both a Trusted IDP and an OAuth2 service provider present in the context of the micro-service sub-account.
As aforementioned, our application is not deployed on BTP, thus we can use a destination service from any BTP sub-account including from the same sub-account as the micro-service.
Trusted IDP.
We need to create a trusted IDP on the micro-service BTP sub-account level.
If using a destination service as a trusted IDP we can simply download the IDP metadata and establish a trust with the micro-service BTP sub-account.
For the sake of simplicity we can use the destination service trust from the same sub-account as the micro-service.
Please refer to the following gist for further details.
OAuth2 service provider.
The BTP micro-service (haa-ina-service) endpoints are protected with OAuth.
When attempting to call the endpoints directly the following payload will be yielded:
<oauth>
<script type="text/javascript">window["_gaUserPrefs"] = { ioo : function() { return true; } }</script>
<error_description>An Authentication object was not found in the SecurityContext</error_description>
<error>unauthorized</error>
</oauth>
Thus in order to make it work there are two options:
- either access the micro-service via a suitable route served by the SAP approuter (through a destination).
- or directly call the destination in the context of the foreign application and provide the obtained bearer access token in the Authorization header in the micro-service endpoint call. A destination service offers a very nice REST API that will come in handy in this scenario. This approach is described in the official SAP help pages, as follows:
The managed application router does not “hide” the back-end microservices in any way; they remain directly accessible when bypassing the application router. So the back-end microservices must protect all their end points by validating the JWT and implementing proper authorization scope checks.
For the sake of simplicity we shall use an instance of the XSUAA service as our OAuth2 service provider.
The instance of the XSUAA service will need to be bound to micro-service application (haa-ina-service) and to the approuter application (haa) as well.
Additionally, with the approuter serving the destination to access the backend micro-service, the approuter application will have to be bound to the destination service.
Quovadis. Building a destination definition.
As aforementioned, a BTP sub-account is acting as a service provider (SP).
In order to build our destination definition we need to download the BTP’s sub-account SP metadata. From BTP’s sub-account SP metadata we shall retrieve two very important saml assertion attributes, namely the audience and the recipient.
The audience attribute designates compatible service providers, in our case this is our BT sub-account and the recipient is the value of the AssertionConsumerService URL which, in turn, will be used by the destination service to retrieve a bearer access token.
The tokenServicePassword is the client secret from the XSUAA service instance service key.
The clientKey and tokenServiceUser are the client id from the XSUAA instance service key.
{
"Name": "Quovadis",
"Type": "HTTP",
"URL": "<backend haa-ina-service service URL>",
"Authentication": "OAuth2SAMLBearerAssertion",
"ProxyType": "Internet",
"tokenServiceURLType": "Dedicated",
"audience": "<entityID from your BTP subaccount SP metadata>>",
"Description": "client_id/client_secret must be the backend service app router's xsuaa credentials",
"authnContextClassRef": "urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession",
"tokenServiceUser": "<xsuaa client_id>",
"HTML5.ForwardAuthToken": "false",
"tokenServiceURL": "<AssertionConsumerService from your BTP subaccount SP metadata>",
"tokenServicePassword": "<xsuaa client_secret>",
"HTML5.DynamicDestination": "true",
"clientKey": "<xsuaa client_id>",
"nameIdFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress",
"scope": "openid",
"SystemUser": "<email>"
}
This destination definition can be either created upfront or could be added to the mta.yaml deployment file to have it created/ updated automatically…
Good to know:
- The destination service will accept either a technical SystemUser or a digitally signed user JWT. It will then generate a saml assertion and will pass it to the OAuth2 service provider for validation and will eventually retrieve a bearer access token.
- SystemUser property comes in handy only for testing/troubleshooting purposes.
- In a productive scenario one will need to provide a digitally signed user JWT token in the X-user-token header of a destination service find destination call. Please refer to official SAP help pages for further details: User Propagation via SAML 2.0 Bearer Assertion Flow | SAP Help
Conclusion
Last but not least, I hope you enjoyed reading this blog. Please provide your feedback in the comments section below.
Overall I was able to demonstrate how to get access to a BTP micro-service from anywhere using an IDP-initiated flow with a BTP sub-account acting as a Service Provider. Literally by-the-book.
You may also refer to appendix and gists for further details on the application structure and build.
Troubleshooting
Please make sure you can call any backend service endpoint directly as follows:
curl -H 'Authorization: Bearer <token>' <backend service URL endpoint>
Appendix
HAA (HANA Analytics Adapter)
This project has been scaffolded using the following Yeoman generator.
Please refer to the following gist for further details.
Build MTA
Please refer to the following gist for further details.
$ mbt build -p=cf --mtar=haa-test.mtar
Deploy MTA
Please refer to the following gist for further details.
$ cf deploy mta_archives/haa-test.mtar
Deploying multi-target app archive mta_archives/haa-test.mtar in org <org> / space <space> as <email>...
Process finished.
Use "cf dmol -i ecfae7d3-88e4-11ec-a86b-eeee0a8*****" to download the logs of the process.
Additional resources
- Secure Your Application on SAP Business Technology Platform Cloud Foundry | SAP Tutorials
- Deploy your AppGyver App to the HTML5 Applications Repository using CLI Plugin | SAP Blogs
- Destination Service – How It Can Be Used? | SAP Blogs
- SAP Application Router | SAP Blogs
- Part 1: How to build an extension application for SAP S/4HANA Cloud using CAP, SAP Cloud SDK and SAP Fiori elements | SAP Blogs
- Principal Propagation between different subaccounts on SAP BTP | SAP Community
- Principal propagation in a multi-cloud solution between Microsoft Azure and SAP Business Technology Platform (BTP), Part I: Building the foundation | SAP Blogs
- Principal propagation in a multi-cloud solution between Microsoft Azure and SAP Business Technology Platform (BTP), Part II: Connecting the system on-premise | SAP Blogs
- SAP Launchpad Service
- Create an HTML5 URL App | SAP Help
- Application Routes and Destinations | SAP Help
- MTA on Cloud Foundry with Html5 App Repo and Approuter | Answers
- SAP Learning Journeys
- SAP Business Application Studio | Youtube