Single Sign-On (SSO), personalized user access to SAP APIs and the application you can build with it
One of the features of a SAP S/4HANA system (even OnPremise 😉) is the availability of a wide variety of available SAP standard oData-APIs. Since APIs are mostly understood only by technical oriented people I wanted to show the power of APIs by building a small application iPhone application that combines usability by providing image recognition functionality with business context based on the underlying SAP system.
Therefore, at first I built an application that looks like this:
The application works pretty simple. You can take pictures with the camera of your phone and an underlying OCR library (Tesseract) analyzes the picture and provides you information about the numbers it recognized on the picture. Now the fun part with SAP S/4HANA begins!
The application will call three different APIs in parallel. The APIs have been exposed to the internet via the SAP API management. Otherwise the iPhone which is accessing your SAP system from the internet would not be able to access them, since (hopefully) your SAP system is not accessible freely in the internet!
Is it a sales order? Is it a delivery? Is it an invoice?
As soon as it gets back a successful result from one of the called APIs, it displays the respective result on the screen. In the above example a picture has been taken from a printed order confirmation and then has been analyzed respectively. But not only does our application know that the scanned document is a sales-order, but it also knows through the sales document flow that a delivery exists in relation to the sales document. In addition, it informs the user about the fact that the delivery has not been posted goods issue yet and it asks the user whether goods issue should be posted.
After pressing “Yes”, goods issue will be posted again via an API in the respective SAP backend system.
After presenting this application several times in front of different audiences I quite often received the exact same feedback ending again with the same question:
“Okay that’s nice and all but how does the SAP-system know which user is accessing the app and which user is then in the end performing the change within the SAP-system?”
That’s absolutely a valid point and I would assume until now the majority of applications use the same solution I have used in the past: A technical user 😭
Even if my solution is just a proof of concept, I wanted to have a more productively usable solution for that. Because a technical user cannot be the final answer for users doing changes or creations within the system (e.g. posting goods issue). In suche cases, you need to know exactly which user triggered the action. Otherwise your changelog will be full of technical users and in the end everyone asks: WHO DID THIS CHANGE?! 😨
Finally, with the SAP API Management I have found a way of providing single sign-on and personalized user access to SAP APIs!
The architecture of the solution is divided into four major building blocks:
- Application: iOS-application developed in Swift
- Identity Provider: Microsoft Active Directory Federation Services
- Connection Providers
- SAP ERP-System: S/4HANA OnPremise Sandbox System
The main parts of the single sign-on solution and personalized user access is the Identity Provider and the Connection Providers. That’s where the magic is happening! So let’s walk through step-by step based on below architecture:
Step 1: Login at ADFS
The flow starts with an API call dedicated to the ADFS. After invoking the API the user will be presented with an ADFS login-screen.
Step 2: Receive oAuth-Token
After successful login the user will receive an oAuth-Token which contains information about the user who has successfully logged in.
Step 3: Call SAP API Management with oAuth Token
Now this token can be used to invoke the API from our backend SAP-system which has been exposed in the SAP API Management. The SAP API Management is a service offered by SAP running in the SAP Cloud Platform
For example the oData-service: “API_OUTBOUND_DELIVERY_SRV” from the OnPremise SAP-system has been used and deployed as API Proxy to the internet.
This oData-service can now be used and all its underlying methods or EntitySets can be invoked.
As Authorization Header we have to use our OAuth Token as bearer.
Step 4: Verify Token with ADFS
After the call arrived at the SAP API Management we first need to verify the token from the ADFS and read its content.
This can be done using the so called policies in SAP API Management:
In the verification step we check and verify the content of the token with the ADFS:
If for example no token is sent or the token contains invalid information this policy will raise an error:
You can do any additional checks based on the content of the token. Since only my specific application should be able to invoke my API proxy I have added a manual policy to check the App-Id of the token.
Step 5: Transfer User Information to SAML assertion
Once the token is verified and all other checks have been passed successfully we will create a SAML assertion based on the information from the oAuth Token. The SAML assertion is then used to call the Connectivity Service of the SAP Cloud Platform.
For this SAP has provided a policy template which we just need to adapt to our SAP Cloud Platform Configuration.
When adding this Policy Template we will find six new policies and additional configuration files added to our Policy-Flow from step 4:
The most important file in this flow is the samlHelper.JS file.
Here we have to set the SAML Audience, the SAML Recipient and the SAML Subject.
- SAML Audience: Can be found in the SCP Cockpit under: Security – Trust – Local Service Provider
- SAML Recipient: Can be found in the SCP Cockpit under: Application – Subscriptions
- SAML Subject: Here we set the SAP-Username which we directly take from the oAuth Token information (unique_name)
Those fields are then used when creating the SAML assertion:
Step 6-8: Call Connectivity Service and Backend System
The Connectivity Service receiving our SAML information is now used to establish a secure connection to the SAP backend system. In our case the backend system is a S/4HANA OnPrem 1909 system but it can be also a R/3 system hosting an oData-service (and exposed via the Cloud connector).
The Connectivity Service uses the so-called Principal Propagation to forward the identity of a cloud user to the Cloud Connector and from there on to an OnPrem system. More technical information can be found here: https://help.sap.com/viewer/cca91383641e40ffbe03bdc78f00f681/Cloud/en-US/d4d3e1e9b2dd44318b49a4812cd51383.html
Based on the SAML-subject (the username) a short-lived X.509 certificate is created which is in the end used to authenticate the user with the SAP backend system.
In the SAP-system the standard authorization procedures for this user will then be executed. That means it is first checked if the user is even authorized to access the system and afterwards if the user has all the privileges to actually do the operations in the system (create, read update or delete).
For example this is how it would look like if you do not have the authorizations for a specific API in the system:
And this is the result you would see if you have no user at all 😎
But now what to do with this? What can we build of it?
So now we have seen the technical architecture of how single sign-on using Microsoft ADFS works. But what can we do with it? Let’s see how based on this technical solution we could adapt our already running iPhone App.
Instead of jumping right into the application itself the app now presents the user with a simple login-screen. When the User clicks on the login-button a redirect to the ADFS takes place. On the following ADFS login-screen you have to login with your ADFS account.
After successful login the app now exactly knows which user is working with the app. So time for an appropriate personal welcome screen 😃
Within the app the user can now choose which functionality should be executed and for each following API call to SAP the respective user credentials from the OAuth Token will be used and the SAP standard authorization concept will be used. All errors regarding authorizations can be displayed directly within the app. A user who has no authorizations to the system at all will get “Your user is not active in the SAP-system” a user who has access to the system but no authorization to call the API will get:
Of course the error message could be more detailed – but in order to keep it simple for the proof and concept I have intentionally kept the error message very straightforward 😃
Based on this proof-of-concept you can see what power lies within the usage of SAP APIs and the SAP API Management. You can start building your own side-by-side applications even with personalized user access. If you are still running a R/3-system instead of S/4HANA you will not find standard SAP oData-APIs available. However, you can also here simply go ahead and start developing your own CRUD-oData-APIs and start building your applications based on your own APIs.
I hope you like my proof-of-concept solution built with the help of the SAP API Management.
Have fun implementing your own solutions and if you have any questions just ask them in the comments!