It enables SAP Principal Propagation with SAP services such as SAP Gateway, S/4HANA Cloud, RISE, and many more using Microsoft Entra ID (formerly Azure AD) as Identity Provider. At the core of the solution is the proven OAuth2SAMLBearer flow.
This way users of your low code solutions spanning the Microsoft and SAP ecosystem are mapped from their Microsoft Entra Id identities to their named SAP backend users. SAP authorizations are fully retained!
In addition to that, solving this challenge on Azure API Management level enables scaling the approach to arbitrary many different consumer solutions. No more re-inventing the wheel for every developer!
Find the policy on the Azure API Management repos for SAP ECC and S/4HANA here and for SuccessFactors here.
Of course, you may deviate from the blueprint outlined based on your scenario across SAP BTP, SAP Graph, Integration Suite, other SAP SaaS solutions etc.
Approach | Principal Propagation Scenarios |
OAuth2SAMLBearer flow | Service to service, on-behalf-of user |
Authorization Code flow | Interactive user session (prone to MFA interference) |
Client Credentials flow | Service to service |
X.509 | Any |
We recommend using OAuth2SAMLBearer, because:- the given scenario in this blog is about app integration and identities known to Microsoft Entra ID, for the integration
- OAuth2 is more flexible and granular control over access to resources
- NetWeaver does not support Client Credentials flow and X509 certificates come with management overhead.
For simplicity and readability of the blog I will refer only to NetWeaver specific settings even though the approach works with any SAP product that supports OAuth2SAMLBearer.
A glimpse under the hood
The API Management policy works under the assumption that trust between your SAP OAuth2 server and Microsoft Entra ID has been setup before.
Have a look at the developer series on our YouTube playlist for a walk-through experience (be warned this was a “without-script exercise” to show pitfalls and how to overcome).
In addition to the existing authorizations maintained on SAP each application consuming the SAP API proxy from API Management need to be authorized on Entra ID.
See this official guide for details on the Entra ID SAML2 setup. See the difference between plain SAML2 and OAuth2SAMLBearer below: Keep close attention to the Entity ID. That is case sensitive! I chased an error once for half a day because of that.
Be aware that Entity ID must be unique in your Entra ID tenant. In case you want to use SAML2 for Fiori SSO and OAuth2 for SAP Principal Propagation for this SID at the same time, you need to maintain both on the Entra ID enterprise app registration. Assign an order (index) that works with your login flow. See below sample for reference.
Take care of your OAuth settings
The steps for the OAuth configuration may vary by SAP product. Here the focus is on NetWeaver.
Move on to your SAP backend and create a user for your OAuth client. For SAP NetWeaver based systems that will be a user of type system with authorizations for S_SCOPE that are relevant for the OData service you want to expose. Both the OAuth2 client user and your SAP end user need S_SCOPE authorization.
Use transaction PFCG to assign the authorization objects to your role or create a new one. I like this blog series for reference.
Verify from transaction /n/IWFND/MAINT_SERVICE that your OData service is enabled for OAuth2.
Birds eye view on the overall process
Below sequence diagram explains an initial login (no cached tokens available yet) performing SAP Principal Propagation using the OAuth2SAMLBearer flow. There are three requests involved:
1. Low Code app login (Entra ID) invoked by the app
2. Token exchange for a SAML2 assertion (Entra ID on-behalf-of flow) invoked by API Management
3. Token exchange of SAML2 assertion issued by Entra ID to SAP access token issued by SAP OAuth2 server. The request is invoked by API Management. The result is a token carrying the authorizations set on the SAP backend (PFCG transaction) for that end user.
As stated at the beginning, the heavy lifting is done by the provided API Management policy.
Once a bearer access token from SAP is available, all requests can be directly served from the API Management token cache. Once it expires – typically after one hour – the refresh token is used to request a new access token. The same is true for the first login step from the low code app.
Import the policy
Learn more about policy creation including Microsoft Copilot use from this article and this video. In case you fancy GitHub Copilot apply the VS Code extension. See this community post for further inspiration.
Consider the governance and security trade-offs between mighty policies and SAP OAuth clients authorized for everything vs. a multitude of clients for each API and scope.
Configure the policy using named values
All the configuration needed for above token exchange flow is best provided with a key value map. Azure API Management offers so called Named values for that. Values can be served from Azure Key Vault or directly maintained here. Mark at least passwords as secrets.
Fill the Named Values as per your environment:
Key | Value sample | Hints |
AADTenantId | 12a345bc-1234-56ab-78ab-zzzzzzzzz | Find it on the Azure portal (e.g. here) |
APIMAADRegisteredAppClientId | 999abce-7777-abcd-a6c9-zzzzzzzzzzz | The Application (client) id of the Entra ID app registration representing your Azure API Management instance. |
APIMAADRegisteredAppClientSecret |
| The secret created for the application 999abce-7777-abcd-a6c9-zzzzzzzzzzz |
AADSAPResource | https://a4h100 | The provider’s name from your NetWeaver SAML setup. Typically, a URL with SID followed Client number |
sap-oauth-client-username | ODATAOAUTH | User name provided on SOAUTH2 transaction (/sap/bc/webdynpro/sap/oauth2_config?sap-client=100)
Create a named user on SU01 with minimum rights (S_SCOPE, S_SERVICE) and reference that on SOAUTH2. Don’t forget to assign authorized scope. |
sap-oauth-client-password | Password for that oauth user | This is only used to request tokens not to authenticate to SAP. |
sap-oauth-scope | ZPRODUCTSVIEW_CDS_0001 | The scope assigned on SOAUTH2. If multiple make a space-separated list. |
SAPOAuthRefreshExpiry | 86400 | Option to set refresh token expiry (default on SAP 2 years). It is not part of the token response. |
SAPOAuthServerAdressForTokenEndpoint | a4h-internal.cloudapp.net:44301 | Host and port of the target SAP OAuth server. |
Avoiding SAP login bursts ("monday morning blues")
People have routines and therefore tend to create clusters of logins at similar times. SAP's OAuth server can become a bottleneck during such periods. We recommend adjusting the default token lifetimes on the SAP OAuth server and implement a random back off delay parameter called “RandomBackOffDelay”.
That parameter ensures that your cached user tokens don't expire all at the same time even though your users tend to login in waves (Monday morning for instance). Our provided APIM policy supports that approach out-of-the-box. See below an example to illustrate the process:
Of course, on the very first day of your implementation when no tokens are cached yet, you are still in trouble ;-) we would recommend to rely on an APIM throttling policy in such cases. Likely you will need to experiment a bit with the SAP refresh token lifetime and backoff-delay parameters to find your individual optimal fit.
Authorize the consuming application with API Management
Authorize the Power Automate SAP OData connector to request tokens for your API Management instance using its client id: “6bee4d13-fd19-43de-b82c-4b6401d174c3” assigning the user_impersonation scope. Verify the id from the Microsoft docs.
Next. verify the client id of your API Management instance is authorized on the app registration attached to your target SAP product (in my sample SAP NetWeaver). And because I was lazy, I gave it the same name. Check the required scope is ticked too ("Scopes = 1" on the bottom table of the screenshot below).
Be aware that your internal policies might require you to actively assign users or groups to the enterprise app registration. Otherwise, you will get an error before you even get to SAP. Been there, done that. Just saying 😉
The final mile of integration
Ok, all homework is done. Now we get to go outside and enjoy the “low code” sun 🌞 Create your SAP OData connection, choose the authentication type Microsoft Entra ID and paste the URI of the Entra ID app registration that represents your API Management.
Clicking on Sign in triggers the $metadata request to your OData endpoint to pull available values.
Private Networking on Azure is a given
Azure API Management supports Azure virtual network integration in all its available "colors". From there you may reach your private SAP crown-jewels👑 on Azure or in RISE securely. Hints on troubleshooting
- SAP’s OAuth server has a tracing tool provided as WebDynpro.
- Open it from SAPGUI with transaction sec_diag_tool or navigate to the web app: “/sap/bc/webdynpro/sap/sec_diag_tool?sap-client=YYY&sap-language=EN”.
- Search for error messages and successful mapping of the Entra ID provided email to the SAP backend user.
- All the settings are client dependent! Always double check it is being applied (or add sap-client URL parameter to be sure). Been there done that 😉 See below transactions to verify setup:
- SAML2 or the webdynpro: /sap/bc/webdynpro/sap/saml2?sap-client=YYY
- SOAUTH2 or the webdynpro: /sap/bc/webdynpro/sap/oauth2_config?sap-client=YYY
- Before applying the API Management policy consider running the sequence of authentication calls locally (with “line of sight” to NetWeaver of course) using a REST client. See this Postman collection for reference. Verify errors from transaction /n/IWFND/ERROR_LOG. Drop cookies in your REST client before re-testing!
- Verify the produced Entra ID tokens attributes using a safe JWT validator (e.g. DevToys). Don’t share your sensitive tokens on some website for validation!
- For the SAML2 assertion exercise the same approach but do base64 decode and XML pretty print. Notepad++ with MIME tools -> Base64 decode and XML Tools -> pretty print does the job locally just fine. Again, don’t paste sensitive info online! Verify the following claims from your assertion:
- AudienceRestriction -> Audience: Should be a URL containing your SID and client id, e.g. https://A4H100
- Claims: Name, email or whatever you have configured to be used to identify the named SAP backend user.
- Cached a faulty SAP token? Consider the following otpions:
- Commenting the lookup of the access token and refresh token on the policy
- Add an APIM endpoint to invalidate the cache using the "cache-remove-value" policy snippet. See this APIM policy to handle your cache for inspiration.
What about Azure?
The connector platform powering Microsoft Power Automate is available on Azure Logic Apps too! The same flows described earlier are applicable. Azure App Service (PaaS), Azure Functions (serverless), and Azure Container Apps (serverless) alike are equipped to do SAP Principal Propagation with Azure APIM too. Any library or SDK enabling Microsoft Entra ID token requests make the scenario work. See a dotnet based implementation here. See the SAP’s Cloud SDK in action running on Azure with Principal Propagation here. The SDK is not mandatory for the scenario but makes handling of SAP OData requests a bliss. Thoughts on production readiness
The OAuthSAML2Bearer flow is an "ever green" discussed in the community at length for years and fully supported by SAP for service to service Principal Propagation. The involved Entra ID app registration client secret can be governed with Azure automation. See this Microsoft article and this GitHub repos for reference.
The SAP and Microsoft low code eco system is a natural fit for productivity across business needs that involve M365 (Microsoft Graph, Teams, Outlook, SharePoint Online, etc.) and SAP.
Final Words
That’s a wrap 🌯. Today you saw how to configure SAP Principal Propagation with Microsoft Entra ID for low code apps. The approach maps Microsoft identities to SAP named users to retain its SAP authorizations. In addition to that you learnt that a provided Azure API Management policy performs the heavy lifting of the authentication flow.
App developers and low coders no longer need to deal with the complexity of the SAP principal propagation and get added benefit of token caching, token refresh, and CSRF handling out-of-the-box.
Cheers
Shailja Nair and Martin