Principal propagation in a multi-cloud solution between Microsoft Azure and SAP Cloud Platform (SCP)
Modern business applications running in the Cloud typically consist of many independent (micro)services. This architectural style enables them to rapidly respond to market conditions. However, such highly distributed systems also come with costs, e.g. for their increased communication overhead and additional operational complexity. Quite often, those services are not deployed in a single system landscape. They are distributed across different regions, geographies (e.g. for availability and performance reasons), or even clouds. In such a multi-cloud setup with multiple platforms from different vendors, interoperability and standards become an important aspect to consider when designing a solution. This is especially true for the security of the solution from an end-to-end perspective.
What does this mean? Let’s start with a simplified scenario of a business application that consists of a frontend component serving web pages to the end users accessing it via their web browser. The frontend also orchestrates the invocation of services in the backend implementing the core business logic. Those backend services may be co-hosted with the frontend component, but may also run on different cloud platforms. Users are authenticated at the frontend by entering their credentials into a login form, or the frontend may delegate this task to a third party, also known as an identity provider (IdP), enabling a single sign-on (SSO) experience to the user. The IdP can be a central user directory managed by the Cloud provider, your own (corporate) user store, or even a “social” IdP such as LinkedIn or Facebook. In all cases, the user is authenticated at the frontend, which then holds a valid session. When the frontend invokes a backend service, the service usually requires the user to authenticate before accessing any data in the backend. The authenticated user or “principal”) is a prerequisite to enforce any authorization rules in the backend. However, asking the user again for their credentials in the backend would be bad idea, both from a security and user experience perspective. Instead, the frontend should securely forward or propagate the principal to the backend to provide a secure and seamless experience. A few things need to be considered for this scenario to work:
- The authenticated user must be “serialized” by the frontend for the call to the backend service in a way that the backend can process it and authenticate the user from this serialized principal without the need to ask the user again for any credentials.
- The principal is transformed into a “security token” which should follow a standardized format. This ensures interoperability between the components of the solution when they are deployed on different platforms and clouds
- Exchanging highly security-sensitive information such as an authenticated user requires the security token to be protected against unauthorized access and modifications. Confidentiality and integrity must be ensured by the underlying security layers of the solution architecture.
- The components exchanging the principal must trust each other. The backend service(s) must only accept principal information sent by the frontend. Therefore, a trust relationship must be established by an administrator of the solution, usually by exchanging a digital certificate which identifies the component(s).
Interoperability and standards
To securely propagate the principal across different platforms and clouds, interoperability at the communication protocol and security token format level are key to the security architecture of the solution. A central standard addressing this scenario for principal propagation is described in RFC 7522, the Security Assertion Markup Language (SAML) 2.0 Profile for OAuth 2.0 Client Authentication and Authorization Grants. This extension to the OAuth 2.0 framework combines the interoperable and mature security token format from the SAML 2.0 standard with a simple request/response protocol from OAuth 2.0. Essentially, it describes how a client (in this scenario the web application frontend) accessing an OAuth-protected resource (the backend service) can obtain an OAuth access token from an OAuth authorization server by presenting a valid SAML assertion as the authorization grant. In this process, the user is not required to approve the token issuance at the authorization server. Other authorization grants of the OAuth 2.0 framework such as the authorization code ask for the user’s explicit permission to allow a client application to access resources on behalf of the user. Since we want to avoid any form of user action such as asking for credentials or user consent, RFC 7522 is the ideal candidate for this scenario.
Detailed scenario walk-through
Let’s take closer look at RFC 7522 in action in a concrete multi-cloud scenario of a web application that has a frontend deployed as an App Service in Microsoft Azure. Data is managed by a backend service running in the Cloud Foundry environment of SAP Cloud Platform, as shown in figure 1 below.
Figure 1: Multi-cloud scenario
The end-to-end process of a user authenticating at the frontend and accessing her data in the backend which performs authorization checks for the logged-in user follows these steps:
- The user (John Doe) accesses a protected resource of the frontend in the web application, which runs as an App Service instance in an Azure subscription. The web application’s frontend is registered in the subscription’s Azure Active Directory (AAD) tenant as an application to delegate authentication to the tenant.
- The web application redirects the user’s web browser to the AAD tenant’s OAuth authorization endpoint (https://login.microsoftonline.com/<tenant_id>/oauth2/v2.0/authorize) where the user enters their credentials and consent to the requested permissions or “scopes” of the web application.
- The frontend now has a session established for the user based on the information contained in the access token from AAD. This token cannot be used to authorize the call to the backend service in SAP Cloud Platform (SCP). Services in SCP only accept access tokens issued by their trusted OAuth Authorization Server, the Extended Services for User Account and Authentication (XSUAA). The XSUAA service is an SAP-specific extension of Cloud Foundry’s standard UAA service. However, (XS)UAA supports the SAML Bearer Grant type according to RFC 7522, which allows the frontend in Microsoft Azure to request an OAuth access token from XSUAA in SCP with a SAML 2.0 assertion. Generating a valid SAML assertion in the frontend would result in a lot of development effort. Fortunately, AAD can provide a SAML assertion in exchange to an OAuth access token which it has issued to the authenticated user before. This feature is a non-standard extension to the On-Behalf-Of (OBO) flow in AAD and follows the general concept of a Security Token Service (STS) as specified by RFC 8693, OAuth 2.0 Token Exchange. When XSUAA receives a SAML assertion issued by an external IDP (here AAD) it has to pass the following validation steps:
- The correct
Audiencewhich is associated with the
Conditionelement of the SAML assertion. It defines under which security conditions the assertion is valid, such as the earliest and latest time instant before it expires, who can consume the assertion, etc. The
Audiencemust match the SAML service provider (SP) value (or
EntityID) of the XSUAA service instance in the SCP subaccount.
- The correct
Recipientwhich is associated with the
Subjectelement of the SAML assertion. It uniquely identifies the subject or user between the IDP (AAD) and SP (XSUAA) for whom the assertion has been issued, defines the format of the user identifier (e.g. an e-mail address). The
Recipientmust match XSUAA service instance endpoint (URL) where the assertion is received.
- A valid signature of a trusted IDP. The IDP (AAD) signs the SAML assertion to proof to the SP (XSUAA) that only it could have issued the assertion. In addition, the signature ensures the integrity of the assertion. Any changes of the assertion data while in transit over the public Internet, whether intentionally or unintentionally, would immediately invalidate the signature. To configure the above values correctly, the frontend app requests the SAML assertion for a second application registered in AAD, which represents the SCP subaccount. This app is created from the AAD SaaS app gallery as an enterprise app of type “SAP Cloud Platform”, which allows to configure SSO settings for SAML. Those settings are taken by AAD when it generates the SAML assertion in response to an OBO flow request. Details of the app registration and configuration are discussed below.
- The correct
- The frontend sends the SAML assertion to the token endpoint of the XSUAA service instance. This request to obtain a valid OAuth access token for the SCP backend service specifies the parameters as defined in section 2.1 of RFC 7522. Upon successful validation of the SAML assertion by XSUAA, a new access token is returned in the response. This access token is issued to the user originally identified by the
Subjectelement in the SAML assertion, and contains additional information required by the backend service to perform authorization checks.
- Finally, the frontend invokes the backend service in SCP with the XSUAA-issued access token sent in the authorization header of the request. The request is executed in the context of the user originally authenticated by the frontend application in Azure.
The next section shows the detailed configuration steps in Azure and SCP to setup the scenario.
Configuration of the scenario is done following these steps:
- Deployment of the backend service in SCP. We’ll use a simple servlet which prints out the logged-in (propagated) principal name and additional attributes
- Configuration of the role collection in the SCP subaccount, and export of the XSUAA SP SAML metadata for setting up the trust relationship
- Registration and configuration of the applications for the frontend and backend in AAD
- Setup of the trust relationship to AAD in the SCP subaccount
A final test with Postman will verify if the end-to-end process works.
Deployment of the backend service
Please make sure that your local environment meets the following prerequisites:
- Download and install the Cloud Foundry CLI
- Download and install the latest version of Maven
- Download and install a Java Development Kit (JDK) Version 8 or later
|1||Clone the repository with the sample code for the scenario using the web URL https://github.com/raepple/azure-scp-principal-propagation.git with your favourite IDE or command line tool.|
|2||Change to the
|3||Login to your SCP subaccount. In the following steps we’ll use a trial account on SCP with the command
|4||Create the XSUAA service instance for the backend service with the command
|5||Build the backend service with the command
|6||Edit the file manifest.yml and replace the string
|7||Deploy the backend service to your subaccount with the command
Configure authorizations for the backend service in SCP
Upon successful deployment of the backend service in SCP, the role and role collection settings for the service must be configured. The role collection is used later in the setup process to assign the permissions to the propagated principal.
|8||Open the SCP Cockpit in your browser and login with your account admin. Navigate to the
|9||Enter “Viewer” as the new role name and click Next. Continue with the configuration of the role attributes, which were defined by the xs-security.json “Viewer” role template. In our scenario, the source of each attribute is the identity provider that originally authenticated the user, so AAD. Enter the following source attribute mappings:
|10||Leave the Role Collection selection empty for now, click Next and then Finish.The assignment to the role collection will be done in the next steps.|
|11||In the Cloud Cockpit, navigate back to the (trial) subaccount level via the breadcromb naviagtion on the top, select Security – Role Collections in the navigation menu, and click on New Role Collection|
|12||Enter a name for the new Role Collection (e.g. “Application User”), click Save, and select the new Role Collection from the list. Click on Add Role and select the newly created Role “Viewer” from the “service” application. Confirm the changes with Save.|
|13||Select Security – Trust Configuration from the navigation menu and click on SAML Metadata to export your (trial) subaccount’s service provider (SP) SAML metadata. Remember where the XML-file is saved – it is used later in Microsoft AAD to simplify the trust setup.|
Finally, we’ll have look up a few configuration settings from the service binding between the “service” app and the XSUAA instance. These settings are required later to successfully request an OAuth access token from Azure with the AAD-generated SAML assertion (step 5 in Figure 1).
Select Spaces from the navigation menu and then your dev space. In Services – Service Instances, select the “service-xsuaa” instance.
|15||Click on Show sensitive data, and copy the values for the following binding properties, e.g. in a temporary text file:
App Registrations and Configuration in AAD
The following steps register the two applications in AAD:
- The first app registration for the frontend web app enables authentication for the user in AAD
- The second app registration represents the SCP subaccount with the backend service and is required to support the On-behalf-of flow to request the SAML assertion (step 4 in figure 1). This app will be registered as an enterprise application from the AAD Gallery
|16||Login to the Azure Portal and select Azure Active Directory from the Azure Services. Select App registriations from the left-hand navigation and click on New registration|
|17||Enter an name for the new app registration of the frontend web app (e.g. “Contoso Web App”). Also provide a Redirect URI which is required for the authentication process, and click on Register.|
|18||Select Manage – Authentication and activate the checkbox for Access Tokens of the Implicit grant. This setting simplifies testing later in the setup process. Click Save.|
|19||Select Manage – Certificates & secrets from the navigation menu and click + New client secret. Enter a description of the new client secret for the web app frontend registration, choose an expiration time, and click Add.|
|20||Copy the newly generated secret in a text file for later use.|
|21||Select Manage – Expose an API from the navigation menu and click + Add a scope. You’ll be asked to set the Application ID URI for the frontend app registration. Accept the proposed default value by clicking Save and continue.|
|22||Choose a name of the new scope (e.g. “scp.access”) and allow Admins and users to consent. Enter the required display name and consent description, and click Add scope.|
|23||Finally, copy the Application (client) ID of the new web app frontend application registration to a text file. This will be required later for configuration and testing purposes.|
|24||Next, register the second app in AAD which represents the backend service in SCP for which the SAML assertion will be requested (step 4 in figure 1). Select Manage – Enterprise Applications from the AAD service navigation menu, and click + New application.|
|25||Enter “SAP Cloud Platform” in the search box, and select the tile for “SAP Cloud Platform” in the search results. Next, enter a name for the new enterprise app, e.g. “SAP Cloud Platform <your trial account name>”. Click Create.|
|26||For the newly created Enterprise Application registration, select the tile “2. Set up single sign on” and select the method “SAML“|
|27||Click Upload metadata file and select the file containing your SCP subaccount’s SAML Service Provider metadata you’ve download in step 13. Click Add.|
|28||Most of the fields in the Basic SAML Configuration are automatically populated by the uploaded metadata file, which greatly simplifies the trust setup between AAD and SCP. For the Sign on URL, enter the value you copied from the url field of the XSUAA service instance binding infomration in step 15. Do not save the settings yet!|
Next, add a new Reply URL. The already existing reply URL was taken from the SAML metadata file and is the Assertion Consumer Service URL for the SAML protocol response message of your SCP tenant-specific XSUAA service instance,
However, for RFC 7522, the SAML assertion is sent to the token endpoint of your XSUAA service instance, which is almost the same URL as for the SAML protocol. Just copy the value of the already existing reply URL, and replace “saml/SSO” with “oauth/token” in the new URL to add.
After adding the new URL, activate the Default checkbox for it. This ensures that the Recipient URL is set correctly in the generates SAML assertion by AAD.
Then click Save.
|30||Next, you will configure additional attributes of the user which will be federated between AAD and SCP. Click on the pencil symbol for User Attributes and Claims|
|31||Select the Unique User Identifier (Name ID) from list and change the Source attribute to user.mail. This will use the user’s email address in AAD as the login name (Name ID) of the subject in the generated SAML assertion. Using the email address is a best practice for a common user identifier when federating users across clouds and platforms.|
|32||To demonstrate federation of user attributes in the scenario, click + Add new claim and enter country in the name field. Select user.country for the Source attribute. Click Save.|
|33||Navigate back to the Setup Single Sign-On with SAML settings and scroll down to the SAML Signing Certificate settings. Click the Download link for the Federation Metadata XML. The downloaded file will be used later to setup the trust relationship in SCP.|
|34||Navigate back to the App Registrations in the AAD service navigation menu. Select All Applications as the filter settings from the top of the list and select the application registered for the backend service in SCP (e.g. “SAP Cloud Platform <name of your trial account>”).|
|35||Select Manage – Expose an API from the navigation menu, and click + Add a client application|
Enter the client ID copied in step 23 into the corresponding field. This will authorize the web app frontend application to request a SAML assertion from AAD for the backend service application.
Confirm with Add application.
Configure trust relationship to AAD in SCP
The trust relationship for SAML is bi-directional. In this step, the exported metadata file from AAD will be imported into the SCP subaccount to finalize the trust setup.
|37||In SCP Cloud Cockpit, navigate back to the (trial) subaccount level via the breadcromb naviagtion on the top, select Security – Trust Configuration from the navigation menu, and click New Trust Configuration|
Upload the metadata file you exported in step 33 and click on Parse. Enter a name for the new trust configuration (e.g. “Contoso Azure AD”) and deactivate the checkbox Available for User Logon, because this IDP is only trusted for non-interactive backchannel SSO, and not for normal user login/SSO.
|39||Configure the authorizations of a user you’ll use for testing with the new trust configuration. Select Role Collection Assignment from the navigation menu, and enter the e-mail adress of a test user in AAD you will use in the next step for testing. Then click Show Assignments|
|40||There are no role collections assigned to the user yet. Therefore, click Assign Role Collection.|
|41||If the user has never logged in to the XSUAA tenant before, you will have to confirm the dialog to add the user first.|
|42||Finally, select the Role Collection “Application User” created in step 12 from the drop down list, and click Assign Role Collection.|
Testing the scenario
After completing the setup in AAD and SCP, let’s verify if the principal propagation works correctly. For testing purposes, we’ll use Postman to simulate the frontend web app. At a later point it is planned to enhance this blog and the associated GitHub repository with a code sample for a web application in Azure which essentially performs the same requests.
Download, install and start Postman, and execute the following steps:
|43||Click Import, select Upload File, and select the Postman Collection file AAD SCP Principal Propagation.postman_collection.json from the Postman folder in the GitHub repository. Then click Import.|
|44||Open the context menu for the imported Collection (…) and select Edit|
|45||Switch to the Variables tab and enter the values for the placeholders:
Click Reset All to update the current values.
|46||Open the collection, select the first request, and click Send.|
|47||Switch to the Console view in Postman, and copy the complete request URL|
|48||Paste the URL in a Web Browser and send the request again. Login with your test user credentials in AAD. The browser will be redirected to a potentially unknown reply URL (e.g. https://webapp.contoso.com/auth). Copy the request parameter access_token from the URL.|
|49||You may want to decode and inspect the access_token with a tool of your choice, e,g, jwt.io|
Open the second request in the Postman collection, switch to the Body tab of the request, and paste the value of the access token. This requests the SAML assertion for the AAD-authenticated user.
|51||Copy the access_token value from the response. This is the SAML assertion generated by AAD. To inspect the content of the SAML assertion, Base64-decode it with an (online) tool of your choice.|
|52||Open the third request in the Postman collection, switch to the Body tab of the request, and paste the assertion as the value for the assertion key.|
Switch to the Authorization tab, select Type Basic Auth, and enter for username the clientid and for password the clientsecret you obtained from the XSUAA service binding in step 15.
|54||From the XSUAA response copy the access_token element. Again, you may want to inspect the token with a tool of your choice.|
Open the last request in the collection. This request calls the backend service in SCP and requires the access token from the above request. Select the Authorization tab and paste the access_token value into the Access Token field.
|56||The response from SCP shows the propagated principal’s name identifier and the additional user attributes which were successfully federated. The principal also obtained the required scopes (“Display”) in SCP to call the backend service based on the Role Collection assignment.|