Skip to Content
Technical Articles
Author's profile photo Martin Pankraz

Embed self-hosted SAP Fiori Launchpad into Microsoft Teams

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

Assigned Tags

      4 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Nils Lutz
      Nils Lutz

      Awesome blog Martin 👏

      and yes Stargate is still a thing, they even think about a  semi-reboot 🙂

      Author's profile photo Martin Pankraz
      Martin Pankraz
      Blog Post Author

      Uhh exciting! Thanks for sharing!

      Author's profile photo Mio Yasutake
      Mio Yasutake

      Hi Martin,

      Interesting blog!

      Regarding allowlist configuration, transaction UCONCOCKPIT maybe relevant.

      It is described in below tutorial (step2 and 3).

      https://developers.sap.com/tutorials/cp-launchpad-federation-prepares4hana.html

      Author's profile photo Martin Pankraz
      Martin Pankraz
      Blog Post Author

      Thanks for the hint Mio Yasutake. Tested that guide today but without success. Allow list and trust setting were not reflecting.