
Note: This blog post is the sixth part of a tutorial series. If you arrived here without reading the first part, please do so before you continue, and then come back here again. Part I explains the key concepts and technology standards for principal propagation in the context of calling a simple Web Service deployed on SAP Business Technology Platform (BTP) on behalf of the authenticated user from Azure Active Directory (AAD). Part II of this blog series extends the scenario by propagating the Azure-authenticated user via BTP and SAP Cloud Connector to an SAP Gateway system. Part III adds a business application to the scenario by implementing a chatbot in Microsoft Teams with the Microsoft Bot Framework V4 SDK, SAP BTP Integration Suite, and Core Data Services in the SAP Gateway system. A live demo of this scenario is available on episode #31 of the great SAP on Azure Video podcast series (starting at min 23:30) from hobruche , goran-condric, and roboban. Part IV uses a “low-code” approach for implementing the chatbot of part III with Microsoft Power Platform, demonstrated in episode #40 of the SAP on Azure Video Podcast series. Part V looks at different aspects for production readiness, such as API management, monitoring and alerting (live demo available on episode #83 in the SAP on Azure video podcast series). I do recommend looking at parts II to V as well to get an in-depth understanding of all bits and pieces, but they are not a prerequisite to implement the solution in this part of the blog series. Part VI (this blog post) starts looking at the reverse direction for propagating the authenticated user (aka "principal") from SAP to Azure. Don't miss SAP TechEd 2022 and check out session XP106 (Single Sign-On and Principal Propagation in Multi-Cloud Environments), where marko.sommer and I focus on this scenario and show a live demo. Finally, part VII looks at principal propagation from Microsoft Power Platform to SAP in the context of making Remote Function Calls (RFCs) and using Business Application Programming Interfaces (BAPIs) with the Kerberos protocol. See episode #142 of the SAP on Azure video podcast series for a live demo of this scenario. |
In the previous parts of this blog series, data has always been retrieved from an SAP-provided service. Part I started the journey with a simple Web Service implemented as a Java servlet deployed on the SAP Business Technology Platform (BTP) Cloud Foundry (CF) environment. From part II onwards, the service is hosted on an SAP Gateway system. With this part, we are turning the data and token exchange flow for propagating the authenticated user (principal) into the opposite direction: The user logs on to a web application on BTP which accesses data on behalf of this user from Microsoft Cloud service resources.
With Microsoft Graph, applications can leverage the rich data set from Microsoft 365 services such as Outlook, OneDrive, Teams and others. Instead of interacting with these services through different Software Development Kits (SDKs), Application Programming Interfaces (APIs), security, messaging and data formats, Microsoft Graph offers a centralized, consistent, RESTful API to access this data. The Microsoft Graph service directs the calls to the right source to free the developer from understanding where exactly the data lives. Graph also aggregates calls for efficiency and performance, and allows the developer to easily traverse the graph of data. This way, it’s easy to build an application that – for example – based on a security alert traverses the graph to see which users might be affected, and for each user, which devices and documents might be affected – thus making it easy to connect data from across many services to enable faster response to threats and asset protection. The Operational Purchaser Chatbot for SAP S/4HANA is an example of an SAP business application using Graph to integrate with Microsoft's collaboration services. It provides a convenient way to initiate an ad-hoc collaboration via Microsoft Teams to reach out to a supplier via the contact data associated with them and create calendar events in Outlook.
This blog post looks at a similar scenario which reads the SAP-authenticated user's calendar events from Outlook. To do so, the web application running on BTP requires an OAuth access token formatted as a JSON Web Token (JWT) with the following content:
The starting point in this scenario is the user's access token issued by the SAP Cloud Identity tenant's authentication service (IAS), indicated as AT(IAS)APP in returned by step 2 in figure 1 below and following the notation <token type>(<issuer>)<audience>. The complete token exchange is orchestrated by the OAuth 2.0 and OpenID Connect (OIDC) authorization and authentication frameworks and their respective token types, which are access tokens (AT), refresh tokens (RT), and identity tokens (ID). Thus, AT(IAS)IAS is an access token, issued by the IAS tenant's OAuth 2.0 authorization server, with an audience set to the IAS tenant's client ID. All tokens except for refresh tokens are formatted as JWTs. Compared to the token exchange in the previous parts of this blog series (see part I, Interoperability and standards, for more details), SAML 2.0 - or more precisely the SAML assertion as an OAuth 2.0 authorization grant defined in section 2.1 of RFC 7522 - is no longer used in this scenario. Instead of transforming between different token formats (JWT to SAML and back to JWT), this scenario only uses JWTs for the token exchange. It is important to note that for this token exchange no direct trust relationship between the application on BTP and Azure AD is required. The application only has a trust relationship to the IAS tenant, and the IAS tenant maintains the trust relationship to the Azure AD tenant (and vice versa).
All authentication requests for the business application on BTP are forwarded by the IAS tenant to the Azure AD tenant which is configured as a corporate identity provider (IdP) in IAS. IAS acts as a proxy and delegates authentication to Azure AD in the role of the relying party to the corporate identity provider. The IAS tenant therefore requires an application registration in Azure AD. The same applies to the business application on BTP which is also registered as an application in Azure AD.
Figure 1: Authentication and token exchange flows
Let's have a closer look at the steps in figure 1:
1. The user accesses the BTP business application's app router URL on BTP, which serves as a single point of entry for an application running in the CF environment. This Node.js based component serves static content, authenticates users as a service provider, rewrites URLs, and can proxy requests to other micro services (such as the Java-based Calendar Service in this demo business application) while forwarding the user infomation obtained from the identity provider. In this scenario, the app router delegates authentication to the IAS tenant using OIDC. It starts the authentication process by redirecting the user' browser to the IAS tenant's OAuth server authorization endpoint at https://<IAS tenant name>.accounts.ondemand.com/oauth2/authorize and sending an OAuth authorization request using the authorization code grant type with the request parameters defined in RFC 6749, section 4.1.1. Those include the application's endpoint (redirect_uri) to where IAS will send the authorization code response to after completing step 4. It further contains the application's client ID generated from the application's binding to the BTP identity services.
2. Because the user is not yet authenticated at the IAS tenant, the user's browser is redirected to the IAS tenant's single sign-on (SSO) endpoint at https://<IAS tenant name>.accounts.ondemand.com/saml2/idp/sso.
3. The business application is configured in IAS to pass all authentication requests to Azure AD as its corporate IdP. Therefore, IAS sends an OAuth authorization request to the Azure AD tenant's OAuth authorization endpoint at https://login.microsoftonline.com/<AAD Tenant ID>/oauth2/v2.0/authorize using the authorization code grant flow. This time, the redirect_uri parameter instructs Azure AD to send the authorization code response back to IAS at https://<IAS tenant name>.accounts.ondemand.com/oauth2/callback. This callback URI must be configured in Azure AD for the IAS tenant's application registration. Otherwise, Azure AD will reject the authorization request.
4.The user gets prompted by Azure AD to enter the credentials. Upon successful authentication, Azure AD sends the authorization code to IAS by redirecting the user's web browser to the URI specified in the previous request (https://<IAS tenant name>.accounts.ondemand.com/oauth2/callback?code=...).
5. IAS receives the authorization code and sends an access token request to Azure AD's token endpoint at https://login.microsoftonline.com/<AAD Tenant ID>/oauth2/v2.0/token according to RFC 6749 (section 4.1.3) by redeeming the code in the code parameter. Azure AD issues an access token and refresh token (RT(AAD)IAS which is cached for later use for the authenticated user with an audience set to the IAS tenant's OIDC name. Figure 2 shows an example for AT(AAD)IAS:
Figure 2: AT(AAD)IAS returned to IAS tenant in step 5
IAS also generates an access token AT(IAS)APP (see figure 3), identity token ID(IAS)APP, and refresh token RT(IAS)APP which are sent back to the application in the response from the previous request in step 4.
Figure 3: AT(IAS)APP returned to business application in the response of step 4
6. The BTP business application requests a client assertion (see the OAuth Client Credentials info box below for more details) from the IAS tenant to use it in the subsequent requests for the token exchange via the IAS tenant's OIDC proxy. The client application sends a token request to the IAS tenant's token endpoint by passing the parameters grant_type with value client_credentials and resource with value urn:sap:identity:corporateidp as body parameters. The POST request is authenticated with the client ID and secret of the business application in IAS. The client assertion from IAS takes the form of a signed JWT as shown in figure 4 that proofs the application's identity to AAD when requesting tokens via the IAS corporate IdP OIDC proxy.
Figure 4: Client assertion AT(IAS)AAD
To ensure that Azure AD accepts this assertion as a valid client credential, Azure AD must trust the IAS tenant as an external issuer (IdP) of the client assertion. This trust relationship is maintained as a federated identity credential (IASTenantFederation in figure 1) in the application registrations for the BTP business application and IAS tenant in Azure AD.
7. The business application exchanges the IAS-issued ID token ID(IAS)APP into an Azure AD-issued access token AT(AAD)APP via the IAS tenant's OIDC proxy token exchange endpoint (https://<IAS tenant name>.accounts.ondemand.com/oauth2/exchange/corporateidp). The POST request uses the assertion parameter to pass the base64-encoded IAS ID token of the user.
8. IAS token service sends a refresh token request using RT(AAD)IAS cached in step 5 to obtain a new access token AT(AAD)APP for the business application, shown in figure 5:
Figure 5: Business application access token AT(AAD)APP
9. The business application uses the Azure AD On-behalf-Of (ObO) flow for requesting the access token AT(AAD)GRAPH required to call Microsoft Graph API on behalf of the logged-in user. This POST request to the Azure AD tenant's token endpoint uses the following body parameters:
The scope parameter instructs Azure AD to generate a new token suitable for calling the Graph API on behalf of the authenticated user as shown in figure 6:
Figure 6: Graph API access token AT(AAD)GRAPH
10. Finally, the business application calls the Microsoft Graph API at https://graph.microsoft.com/v1.0/me/calendar/events to read the signed-in user's calendar events. This HTTP GET request uses the authorization header to send the user's AT(AAD)GRAPH Graph API token according to RFC 6750. The response (see figure 7) contains the Open Data Protocol (OData)-compliant calendar events of the user:
Figure 7: OData response payload from Graph API
The response payload starts with the @odata.context element containing the Azure AD tenant-wide unique user's object ID (see oid claim in figures 2, 5 and 6) in the Graph API query URL. The value element holds an array of calendar events for this user.
OAuth Client Credentials |
Using client ID and client secret is the most common method to authenticate a client application's token request to an OAuth authorization server. From a security and administration perspective, this type of client credentials has some drawbacks:
|
Check out the code for the BTP application with
git clone https://github.com/raepple/azure-scp-principal-propagation.git git checkout part6
If you haven't already done so from your setup in part I, make sure you have the following tools installed on your local development environment:
Furthermore, access to the following cloud services is required:
The token exchange and OIDC proxy setup between the business application on BTP, IAS, and the Azure AD tenant, requires a trust relationship which is established by registering two applications in the Azure AD tenant (see figure 1):
Step | Description | Screenshot |
1 | Login to Azure Portal (e.g. with your Microsoft 365 E5 developer subscription’s admin account) and select Azure Active Directory from the portal menu. Select App registrations from the left-side menu. | ![]() |
2 | Click + New registration | ![]() |
3 | Enter "SAPIASTenant" for the Name of the new application registration. Select "Web" from the dropdown list in the Redirect URI section. Enter your IAS tenant's redirect URI in the Redirect URI section's text field: https://<IAS tenant name>.accounts.ondemand.com/oauth2/callback. Replace <IAS tenant name> with your tenant's name. Click Register. | ![]() |
4 | Copy the newly generated Application (client) ID to a temporary text file. You will need it in the next step for deploying the sample application. | ![]() |
5 | Select Manifest from the navigation menu to edit the application registration's manifest file. Change the value for the fieldaccessTokenAcceptedVersion from null to 2. Click Save. | ![]() |
6 | Click on the breadcrumb naviation to return to the list of application registrations. | ![]() |
7 | Click + New registration | ![]() |
8 | Enter "SAPBTPGraphApp" for the Name of the new application registration. Click Register. | ![]() |
9 | Copy the newly generated Application (client) ID to a temporary text file. You will need it in the next step for deploying the sample application. | ![]() |
10 | Select Manifest from the navigation menu to edit the application registration's manifest file.Change the value for the fieldaccessTokenAcceptedVersion from null to 2. Click Save. | ![]() |
Step | Description | Screenshot |
11 | Open the file vars.yml from the BTP subdirectory of your Git repository's local copy in an editor. | ![]() |
12 | Change the following placeholder values:
Save the changes. | ![]() |
13 | Open the file manifest.json from the BTP/application/src/main/webapp subdirectory and change the placeholder values in line 57:
Save the changes. | ![]() |
14 | Open the file MainView.controller.js from the BTP/application/src/main/webapp/controller subdirectory and change the placeholder values in line 13:
Save the changes. | ![]() |
15 | Open a command prompt and change to the BTP subdirectory Run mvn clean package. The build process should end with a BUILD SUCCESS message. | ![]() |
16 | Login to your SAP BTP CF subaccount with the command cf login -a https://api.cf.<region>.hana.ondemand.com Replace <region> with your subaccount's region, e.g. ap21. Enter your subaccount administrator's email and password and select your target org and space. | ![]() |
17 | Create a new service instance of the SAP BTP identity service with the command cf create-service identity application ias-btpgraph | ![]() |
18 | Create a new service instance of the SAP BTP destination service with the command cf create-service destination lite destination-btpgraph | ![]() |
19 | Run the command cf push --vars-file ./vars.yml This will deploy the application's components to your SAP BTP CF subaccount. | ![]() |
20 | Login to the SAP BTP Cockpit and navigate to your CF subaccount. | ![]() |
21 | Go to Cloud Foundry > Spaces in the navigation menu. Click on the space selected for the deployment of the application. | ![]() |
22 | Go to Services > Instances in the navigation menu. Select the ias-btpgraph service instance from the list. Click View Credentials. | ![]() |
23 | Copy the value of the clientid element in line 2 to a temporary text file. This is the OAuth client ID of the business application in the IAS tenant. You will need this id in the next step to configure trust to your IAS tenant in Azure AD. Click Close. | ![]() |
Trust to the IAS tenant is configured in Azure AD with a new federated identity credential. In addition, a client secret is required for the initial token exchange in step 5 of figure 1. Both credentials will be configured for the application registrations in the following step.
Step | Description | Screenshot |
24 | Go back to the Azure Portal from step 10. Select Certificates & secrets from the navigation menu of the SAPBTPGraphApp application registration. Switch to the tab Federated credentials. Click Add credential. | ![]() |
25 | Select Other Issuer from the Federated credential scenario dropdown list. | ![]() |
26 | Enter the following values:
Click Add. | ![]() |
27 | Navigate back to the App registrations with the breadcrumb navigation. | ![]() |
28 | Select the SAPIASTenant app from the list. Select Certificates & secrets from the menu and switch to the Client secrets tab. Click + New client secret. | ![]() |
29 | Enter "OIDCProxy" for the Description. Click Add. | ![]() |
30 | Click Copy to clipboard in the Value column and paste it to a temporary text file. You will need it later in the setup process. | ![]() |
31 | Switch to the tab Federated credentials. Click + Add credential. | ![]() |
32 | Enter the following values:
Click Add. | ![]() |
To request the Outlook calendar event on behalf of the user, the business application (SAPBTPGraphApp) requires the Graph API permission Calendars.Read. SAPBTPGraphApp also exposes the custom scope "token.exchange". This scope is referred to as a (downstream) API permission for the SAPIASTenant application registration and required for steps 7 and 8 in figure 1. For the initial token request to Azure AD (see step 5 in figure 1 and figure 2), the SAPIASTenant application exposes the custom scope "ias.access".
Step | Description | Screenshot |
33 | Go to Expose an API in the navigation menu. Click + Add a scope. | ![]() |
34 | Accept the default value for the Application ID URI. Click Save and continue. | ![]() |
35 | Enter "ias.access" for the new Scope name. Provide an Admin consent display name and description. Click Add scope. | ![]() |
36 | Copy the full-qualified URI of the new scope (api://<client id>/ias.access) from the clipboard to temporary text file. It will be used in a later setup step. | ![]() |
37 | Click on the breadcrumb naviation to return to the list of application registrations. | ![]() |
38 | Select the SAPBTPGraphApp application from the list. Choose API permissions from the navigation menu. Click + Add a permission. | ![]() |
39 | Click the Microsoft Graph tile. | ![]() |
40 | Click the Delegated permissions tile. | ![]() |
41 | Enter "Calendar" in the search text box. From the search results, activate the checkbox for the Calendars.Read permission. Click Add permissions. | ![]() |
42 | Click Grant admin consent for <Azure AD tenant name> and confirm with Yes so that the user is not prompted to consent to the Graph permissions used by the application. | ![]() |
43 | Navigate to Expose an API in the menu. Click + Add a scope. | ![]() |
44 | Accept the default value for the Application ID URI. Click Save and continue. | ![]() |
45 | Enter "token.exchange" for the new Scope name. Provide an Admin consent display name and description. Click Add scope. | ![]() |
46 | Click on the breadcrumb naviation to return to the list of application registrations. | ![]() |
47 | Select the SAPIASTenant application from the list. Choose API permissions from the navigation menu. Click + Add a permission. | ![]() |
48 | Switch to the tab My APIs | ![]() |
49 | Select the SAPBTPGraphApp from the list. Activate the checkbox for the token.exchange permission. Click Add permissions. | ![]() |
50 | Click Grant admin consent for <Azure AD tenant name> and confirm with Yes so that the user is not prompted to consent to the requested permissions of the SAPIASTenant application. | ![]() |
Step | Description | Screenshot |
51 | Login as an administrator to your SAP Cloud Identity service administration console at https://<IAS tenant name>.accounts.ondemand.com/admin | ![]() |
52 | Go to Identity Providers > Corporate Identity Providers and click Create. Enter a Display name (e.g. "Azure Active Directory") and click Save. | ![]() |
53 | Click on Identity Provider Type from the Trust settings of the new corporate identity provider. | ![]() |
54 | Select OpenID Connect Compliant from the list. Click Save. | ![]() |
55 | Click on OpenID Connect Configuration from the Trust settings of the new corporate identity provider. | ![]() |
56 | Enter your Azure AD tenant's OIDC Discovery URL (https://login.microsoftonline.com/<AAD tenant ID>/v2.0) Click Load. The Issuer field gets populated from the loaded Azure AD tenant's OIDC metadata. | ![]() |
57 | Enter the SAPIASTenant's client ID in the Client ID field. In the Client Secret field, enter the value of the OIDCProxy secret copied in step 30. Click Validate. | ![]() |
58 | Verify a successful validation of the OIDC configuration. Click OK. | ![]() |
59 | Click + Add | ![]() |
60 | Copy and paste the full-qualified URI of the SAPIASTenant application's custom scope (api://<client id>/ias.access) copied in step 36 for the new scope. Click Save. | ![]() |
61 |
Click + Add again and add the scope "offline_access". | ![]() |
62 | Click Save. | ![]() |
63 | Go to Applications & Resources > Applications Select the application ias-btpgraph from the list which was created from the identity service binding. Click OpenID Connect Configuration from the Single Sign-On settings. | ![]() |
64 | In the Redirect URIs section, click Add. | ![]() |
65 | Enter the business application's OAuth 2.0 redirect URL, which is at https://approuter-btpgraph-<ID>.cfapps.<region>.hana.ondemand.com/login/callback. Replace <ID> and <region> with the values you used in step 10. Click Save. | ![]() |
66 | In the Conditional Authentication settings of the application, click Conditional Authentication. | ![]() |
67 | Select the Corporate Identity Provider created in step 52 from the dropdown list as the Default Authenticating Identity Provider for the ias-btpgraph application. This will forward all authentication requests from the business application to the Azure AD tenant. Click Save. | ![]() |
The application uses the SAP Cloud SDK to authenticate against the SAP BTP destination service and retrieve the following destinations into the application:
Step | Description | Screenshot |
68 | Go back to the SAP BTP Cockpit and navigate to your CF subaccount. Select Connectivity > Destinations from the navigation menu. Click New Destination. | ![]() |
69 | Enter the following values for the first destination:
Click Save. | ![]() |
70 | Repeat steps 68 and 69 with following values for the second destination:
Click Save. | ![]() |
71 | Repeat steps 68 and 69 with following values for the third destination:
| ![]() |
Step | Description | Screenshot |
72 | Open a new web browser (e.g. in a private window) and go to the URL of your business applications's approuter at https://approuter-btpgraph-<ID>.cfapps.<region>.hana.ondemand.com/ Replace <ID> and <region> with the same values from step 12. Because the business application in the IAS tenant is configured to forward the authentication request to the corporate IdP, the user is prompted by the Azure AD tenant to enter their credentials. Enter your test user's email address and click Next. | ![]() |
73 | Enter your user's password and click Sign in. | ![]() |
74 | As a logged-in user, you can see your calendar events listed by application in the UI5 frontend. At this time there may be no events found. | ![]() |
75 | Open a new browser tab and login to the Outlook web interface at https://outlook.office.com/calendar/view/month You will be single signed-on with your test user. Click New event. | ![]() |
76 | Choose a title for the new event and click Save. | ![]() |
77 | Go back to the previous browser tab and refresh the business application’s page (Ctrl+R). This time the application lists the new calendar event you’ve just created for the user. By requesting the Graph API token as shown in figure 1, the application could retrieve the data on behalf of the IAS- and Azure AD-authenticated user. | ![]() |
78 | To take a look behind the scenes, open the application’s debug page at https://approuter-btpgraph-<ID>.cfapps.<region>.hana.ondemand.com/debug This page lists the tokens in Base64-encoded format that are exchanged between BTP, IAS and Azure AD. | ![]() |
79 | Copy the value of the Graph access token (last token in the list) and paste its value into a JWT debugger tool such as https://jwt.ms | ![]() |
With this part of the blog series you’ve successfully implemented principal propagation starting from the authenticated user in SAP BTP calling a service in the Microsoft Cloud, which is equally important than the opposite direction covered by the previous parts. A big thank you goes to the security product teams on the SAP- and Microsoft-side who worked hard in the last months to enable this scenario.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
20 | |
19 | |
9 | |
7 | |
5 | |
5 | |
5 | |
5 | |
5 | |
4 |