Skip to Content
Technical Articles
Author's profile photo Volker Buzek

local with remote BTP authentication

A common demand amongst UI5 developers is that whilst working on a UI5 app locally, remote services and destinations from the SAP Business Technology Platform (BTP) should still be usable at dev time. This requires an authentication to BTP when the application is running locally – but the UI5 tooling, which is preferred way of doing local UI5 development with, isn’t capable of hooking up SAP BTP as an Identity Provider.

Nevertheless, with the most current version of ui5-middleware-cfdestination and a little hack, you can achieve this additional CloudFoundry for your pocket 🙂

Here’s what you’ll need (file system layout taken from a easy-ui5-scaffolded UI5 app)

├── default-env.json
├── uimodule
│   ├── index1.html
│   ├── ui5.yaml
│   └── webapp
# ...
│       ├── index.html
# ...
└── xs-app.json


Adjust the cfdestination middleware config in ui5.yaml and set both allowLocalDir: true and authenticationMethod: "route"; while you’re at it, notice the port the included approuter is running on (here: 5000)

  # ...
  - name: ui5-middleware-cfdestination
    afterMiddleware: compression
      debug: false
      authenticationMethod: "route"
      allowServices: true
      allowLocalDir: true # <- brand-new config option
      port: 5000
      destinations: # ...



A default-env.json, containing the BTP credential information. It is the prerequisite for any authentication flow with @sap/approuter in the Node.js- and HTML-CloudFoundry services.

Best use a cf cli plugin to retrieve the file from the BTP (sub-)account of your choice:


A route in xs-app.json, the @sap/approuter config file, pointing to a local static asset that is protected by an approuter-based authentication

    "authenticationMethod": "route",
    "routes": [
    // ...
            "source": "^/index1.html",
            "target": "index1.html",
            "localDir": "uimodule",
   			"authenticationType": "xsuaa"
    // ...

The above configuration tells the approuter to act on a URL http://localhost:$app-router-port/index1.html, map it to the local path uimodule/index1.html, and protect that route via (OAuth2 password grant-type) authentication.

temporary static HTML file

All three above were standard UI5- and BTP-environment files. Now comes the hacky part.

The “temporary” static HTML file (here: index1.html) is not part of the actual UI5 app, but exists standalone. Its’ sole purpose is to trigger the authentication flow and route to the actual UI5 app.

For the latter to work, the file contains a client-side redirect pointing to the bootstrap URL of your UI5 app, as it’s served by the UI5 tooling (here: http://localhost:8080/index.html).

<!-- ... //-->
  <meta http-equiv="refresh" content="0;url=http://localhost:8080/index.html" />
<!-- ... //-->

That’s it, configuration-wise.

starting things

Run ui5 serve as usual for starting the development server – this per default starts the UI5 application on port 8080, with the ui5-middleware-cfdestination running a @sap/approuter under the hood.

Now, instead of hitting http://localhost:8080 (which is the default UI5 tooling URL), utilize the @sap/approuter serving the above static HTML “hack” asset by opening http://localhost:5000/index1.html – this will make the approuter pick up the protected resource and cause the client-side redirect to the BTP/IdP configured in your local default-env.json.


Et voilà – first step achieved: remote authentication triggered from the local setup!

After successful login, the meta-tag based redirect will -well- redirect you from http://localhost:5000/index1.html to http://localhost:8080/index.html – the local UI5 app. And that gives you an authenticated BTP session for your local UI5 development runtime!

Which, in turn, fullfills the original requirement: now you can use all applicable remote services of your BTP (sub-)account for your local UI5 development!

Here’s the whole flow in animation:


By the way: an example setup can be found over at SAP Champion and SAP Online Track organizer Ronnie Sletta’s GitHub account: (once the PR is in 😀 merged now 🥳).

Now, go ahead and enjoy the best of both worlds, local development with remote BTP capabilities!



Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Ronnie André Bjørvik Sletta
      Ronnie André Bjørvik Sletta

      Thanks Volker Buzek, for the amazing work you do and all the effort you put into helping me with this use case. ♥️

      I have merged the PR by the way, so it is included in the local setup with Visual Studio Code and dev containers demo repo.

      Author's profile photo Cedric Heisel
      Cedric Heisel

      Hi Volker,

      I was on my way preparing a blog post about this wonderful middleware for ui5 tooling as I think it needs more attention out there in the community. It's a wonderful approach to develop ui5 apps and debug with the real backends.

      Thank you for showing up how to use it - good post!




      Author's profile photo Volker Buzek
      Volker Buzek
      Blog Post Author

      don't hold back, put that blog post idea of yours into action and publish it!

      Author's profile photo Pieter Janssens
      Pieter Janssens

      Hi Volker,

      Good stuff, thanks.

      I was achieving a similar result through a combination of a local @sap/approuter and ui5-middleware-simpleproxy, where I forwarded all requests to localhost:5000. I can see this somewhat being easier to setup, but I would maybe package it separately in ui5-middleware-approuter for increased hit ratio on related search results + support reading the destinations from default-env.json (CAP srv-api).

      I gave ui5-middleware-cfdestination a go because I didn't manage to get ui5-middleware-stringreplacer to work i.c.w. ui5-middleware-simpleproxy, but unfortunately it seems to give the same result: strings are not replaced when the resources are served through the middleware.

      Best regards,


      Author's profile photo Pradeep B
      Pradeep B

      Thanks a lot for this tutorial!