Dear community,
The
last post in this series looked at embedding the SAP Portal service hosted on SAP Business Technology Platform (BTP) into Microsoft Teams. Feedback showed that the
self-hosted Fiori Launchpad (FLP) option would be also top of mind. So, here it goes…
Off we go again through the gate to find that new species of life out there in the galaxy that lives in both worlds – SAP and Microsoft – at the same time! (Stargate still a thing? Just curious)
Fig.1 Illustration of self-hosted Fiori in Teams; source for stargate illustration: Wikipedia, by Stefan Xp, CC BY-SA 3.0, image used as overlay as is
Embedding an external page into a web app (including the Teams desktop or web client) is straightforward. iFrames are a popular option to get it done.
Fig.2 Click path to embed external website
Single-Sign-On (SSO) between SAP Fiori and Azure AD has been discussed on the community a lot, so I won’t repeat. Find the official Microsoft docs for the process
here.
Let’s look at the moving parts
Nowadays web applications and particularly PaaS or SaaS apps prohibit embedding by default to protect user experience, limit attack vectors, or for branding reasons for instance. In addition to that SAP positions
SAP WorkZone and
BTP services over the
self-hosted Fiori Launchpad.
Unfortunately, that means our journey to embed our self-hosted Fiori Launchpad into Teams won’t be as plug & play as with the BTP Cloud Portal. The configuration goals regarding Browser Content Security Policies (CSP), trusted domains and iFrame embedding however stay the same.
Let’s see where we are with our current configuration: I am using S/4HANA 1909 with NetWeaver Basis release 7.54. Same is true for my SAP Gateway. Given the basic nature and type of configurations we are going to perform, the approach should be downwards compatible to ECC and lower Gateway releases. Let me know if you hit road blocks with lower releases on the comments.
Off we go🏃🏿
♀️: When you start fresh, you will likely see below message, when you simply try to link your FLP on your Teams Tab or Channel:
"The parent window did not answer when requesting the origin"
Fig.3 Error message when opening Fiori Launchpad in Teams
With custom portal apps or any service that you control yourself, you would look to adjust the framing response to cater for SAP’s specifics. Here is how that might have looked like in the old days using the Window postMessage API from the originating frame to load the FLP:
window.addEventListener('message', function (event) {
if (event.data === 'SAPFrameProtection*require-origin') {
event.source.postMessage('SAPFrameProtection*parent-unlocked', '*');
}
});
Finally fronting your framing portal application and your Fiori Launchpad with a reverse proxy would have gotten you where you wanted to be. Like I said… in the old days
👴🏾
Since Microsoft Teams is a global SaaS application, you have no power to influence the framing behaviour by design. Also, you cannot front it with a reverse proxy. What then?
Custom app with Teams SDK to gain more freedom? Let’s try overriding default configuration first.
Establish trust
You need to convince the Fiori Launchpad to trust teams.microsoft.com to embed it. There are multiple ways to tackle this. In this blog I will describe an approach that relies on overriding the CSP behaviour. To do so you need to re-define the login class for the ICF service for FLP (transaction SICF).
Fig.4 Custom login class create wizard inheriting from CL_FIORI3_LOGIN
Your custom class needs to inherit from
/UI2/CL_FIORI3_LOGIN (at least for S4 1909+. For other releases adjust accordingly for the class mentioned there).
class Z_CUSTOM_LOGIN definition
public
inheriting from /UI2/CL_FIORI3_LOGIN
final
create public .
public section.
methods CONSTRUCTOR
importing
!II_SERVER type ref to IF_HTTP_SERVER optional .
protected section.
private section.
ENDCLASS.
CLASS Z_CUSTOM_LOGIN IMPLEMENTATION.
* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method Z_CUSTOM_LOGIN->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] II_SERVER TYPE REF TO IF_HTTP_SERVER(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
method constructor.
super->constructor( ii_server ).
m_content_security = `default-src 'self'; frame-ancestors 'self' https://teams.microsoft.com;`. "#EC NOTEXT
c_login_params-nodefaultframebust = 'Y'.
endmethod.
ENDCLASS.
Please check official prerequisites
here for most up to date guidance. Currently recommended domains for the CSP frame ancestors settings are:
- teams.microsoft.com
- *.teams.microsoft.com
- *.skype.com
Replace the System Logon configuration with your custom class accordingly.
Fig.5 Click path to adjust Logon implementation class
Before we move on also drop the parameter LOGIN_FRAMING_ENABLED from the settings or change it to false (0):
Fig.6 Screenshot of GUI configuration parameter for FLP service
So far so good
👍. Let’s try opening the FLP on Teams again. Can I get a drum roll?
🥁ah, much better!
Fig.7 Screenshot of successful load of Fiori Launchpad logon page
As of now you could switch on SSO, because the redirect will now work. So, let's login and continue. The Launchpad loads...but wait! What’s up with my mouse cursor
🚫?
Fig.8 Screenshot of fully loaded Fiori Launchpad with "deny" cursor
So, still not quite there yet. Maybe that error message on the developer tools (ctrl+shift+i) console points us in the right direction?🧐
After some search on the SAP docs, you will end up on the
SAPUI5 docs or its counterpart for
NetWeaver and learn about the different UI5 framing options and the "allowlist service". To apply the configurations, we need to locate the Fiori Launchpad files on the NetWeaver. SAP describes that on their
Interface AddOn docs.
Find the relevant html file for the self-hosted FLP using transaction SE80 for instance and inject/adjust the property
data-sap-ui-frameOptions="allow".
⚠️
Be aware: FioriLaunchpad.html is an SAP provided standard file. Changing it is not upgrade-safe. Therefore, the adjustment of the frameOptions setting needs to be added to your manual post-upgrade SAP Basis procedures. |
Fig.9 Screenshot from SE80 and frameOptions setting of Fiori Launchpad html file
So far, I couldn’t get the configuration to work with the desired "trusted" option. Maintaining the
allow-list string array and the backend table HTTP_WHITELIST as per SAP note
2142551 didn’t lead to success yet.
@Community do you have any further guidance, hints, and experience regarding that aspect? 🙋🏽
At this point, you need to adjust that frameOptions setting to "allow" (don’t forget to save and activate) for a fully functional embedded experience unfortunately. With that theoretically every website on this planet would be allowed to frame your FLP login page and increase exposure to attack vectors that are mitigated by that CSP policy.
But ask yourself: Is my FLP even reachable from outside my company network boundary? Even if it is, doesn’t my web application firewall (WAF) mitigate that risk sufficiently? Have a look
here to read more about applying WAFs for Fiori Launchpad.
Once you made a conscious decision to apply above configuration, you will find that breath-taking life form on the other end of our "Portal-Gate" from fig.1, that thrives both in the SAP
and the Microsoft world…
Fig.10 Fully functional Fiori Launchpad embedded in Microsoft Teams including SSO
Beautiful, isn’t it?
🐈🦄
Be aware: the Teams Desktop client running in its secure container is more forgiving than the web client. But since you often don’t know how your users consume Teams, I would still advise to configure for proper browser access too. Guidance in this blog referred to the web client. |
Choose your preferred option of embedding in Microsoft Teams
To support the story in this post, a simple Tab-Embedding was chosen linking to the Launchpad landing page. But Teams offers more personalized options too. Have a look
here to get started. Even linking to a specific Fiori app directly using its Launchpad navigation link might be more desirable.
See below a simple example to create a
personal Teams tab for a dedicated Fiori app (Maintain Business Partner – SAP GUI for HTML example) that goes beyond URL linking.
Note: The approach can be applied to BTP hosted apps too.
Fig.11 Screenshot of embedded Fiori app as personal tab in Teams
To reproduce my example, utilize the Teams sample "
tab-personal > razor-csharp". Be aware that you need to enhance the CSP policy on your Z_CUSTOM_LOGIN class to support
ngrok and localhost for local testing. You can drop localhost for the Teams preview feature. Also keep in mind during your testing that ngrok generates a new URL each time you re-create the tunnel!
Fig.12 Screenshot of Apps Developer Portal before Teams preview of SAP app
method constructor.
super->constructor( ii_server ).
m_content_security = `default-src 'self'; frame-ancestors 'self' https://teams.microsoft.com https://e6ce-2003-cd-6728-7724-b120-6ec-7c82-2c9.ngrok.io http://localhost:3978`. "#EC NOTEXT
c_login_params-nodefaultframebust = 'Y'.
endmethod.
See below the changes I did to the sample files to support the prototype:
PersonalTab.cshtml
@page "/personalTab"
@{
Layout = "_Layout";
}
<!DOCTYPE html>
<html>
<body>
<script>
//add call to microsoftTeams here.
app.initialize()
</script>
<iframe src="https://your-path-to-SAP-Gateway/sap/bc/ui2/flp" style="height: 100%; width: 100%;"></iframe>
</body>
</html>
Site.css: keep as is and only strip html and body like below for proper frame height and width:
html {
height: 95%;
}
body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
height: 100%;
}
Troubleshooting hint
Use the Teams Web client, so you get access to the developer tools (Ctrl+Shift+I) and error logging insights alongside the html dom tree with your applied settings. On the Desktop Client you have no access to error messages.
Pay attention to the automatic redirect setting for the IdP in case you have issues with the SSO and multiple configured IdPs. Tobias Hofmann created a nice
post for it.
Thoughts on production readiness
The individually described configurations and settings are fully documented by SAP and Microsoft and linked on each section even though the overall process is not.
Embedding the self-hosted Fiori Launchpad into other portal apps is a common practice. Azure AD and SAP apps are a natural fit and being applied as identity provider for many years also for SSO.
Only drop of bitterness is the not yet discovered configuration combination that allows keeping the frameOptions on "trusted" rather than "allow".
Any help here
@community?🙋🏻
♀️ No luck yet reverse engineering myself.
If you are unhappy with the not-upgrade safe custom configuration approach, you can always go all-in and develop a
fully fledged Teams app and re-use the SAP OData service powering the Fiori app of your desire. The same approach can be applied to BTP-based services as described in my
first post or
Power Apps. Have a look
here to get started with Teams native extensions and OData.
Final Words
Not too bad, huh? We investigated SAP Fiori Launchpad embedding challenges today and learned how to configure custom handling to overcome these. We used Azure AD and Microsoft Teams as examples to support the approach. As cherry on the cake
🍰, we linked a specific SAP app as personal Tab on Teams for a more personalized experience.
What do you think
@community? Anything to add?
Find the sister blog post on BTP Fiori Launchpad or Cloud Portal service
here.
As always feel free to ask lots of follow-up questions.
Best Regards
Martin