Skip to Content
Technical Articles
Author's profile photo Mio Yasutake

Getting User Information in BTP Launchpad

Introduction

Sometimes, we need logged-in user information (such as ID, first name or last name) in our apps.
You can use User API Service of approuter for this purpose if your app is working behind an approuter. Here is a quote from the document:

The application router exposes a user API that returns the details of the user who is logged in. This API supports two endpoints: /currentUser and /attributes. The /currentUser endpoint returns all details of logged in users, while the /attributes endpoint returns the main user properties.

If you build an application using Managed Approuter which is available in BTP Launchpad, all you have to do is just to add a route to xs-app.json file. In this post, I’m going to demonstrate how you can show user info in a simple Fiori app in BTP Launchpad.

 

Steps

  1. Generate an UI5 project
  2. Add a route to xs-app.json
  3. Write controller code to get user info
  4. Deploy to the Cloud Foundry

 

1. Generate an UI5 project

I use easy-ui5 to generate a project.

yo easy-ui5 project

Chose “SAP Launchpad service” for the question “On which platform would you like to host the application?”

 

2. Add a route to xs-app.json

Add the following route to webapp/xs-app.json file.

    {
      "source": "^/user-api/currentUser$",
      "target": "/currentUser",
      "service": "sap-approuter-userapi"
    },

The endpoint /user-api/currentUsers returns user info in the following structure.

{
   "firstname": "John",
   "lastname": "Doe",
   "email": "john.doe@sap.com",
   "name": "john.doe@sap.com",
   "displayName": "John Doe (john.doe@sap.com)"
}

 

3. Write controller code to get user info

Add the following code to the controller. Here I’m loading user data into a JSON model called “userInfo”. Using this model you can retrieve user data or bind it to the view.

sap.ui.define([
    "demo/userapi/controller/BaseController",
    "sap/ui/model/json/JSONModel"
], function (Controller, JSONModel) {
    "use strict";

    return Controller.extend("demo.userapi.controller.MainView", {
        onInit: function () {
            this.getUserInfo();
        },
        getUserInfo: function () {
            const url = this.getBaseURL() + "/user-api/currentUser";
            var oModel = new JSONModel();
            var mock = {
                firstname: "Dummy",
                lastname: "User",
                email: "dummy.user@com",
                name: "dummy.user@com",
                displayName: "Dummy User (dummy.user@com)"
            }; 

            oModel.loadData(url);
            oModel.dataLoaded()
            .then(()=>{
                //check if data has been loaded
                //for local testing, set mock data
                if (!oModel.getData().email) {
                    oModel.setData(mock);
                }
                this.getView().setModel(oModel, "userInfo");
            })
            .catch(()=>{               
                oModel.setData(mock);
                this.getView().setModel(oModel, "userInfo");
            });
        },      
        
        getBaseURL: function () {
            var appId = this.getOwnerComponent().getManifestEntry("/sap.app/id");
            var appPath = appId.replaceAll(".", "/");
            var appModulePath = jQuery.sap.getModulePath(appPath);
            return appModulePath;
        },        

    });
});

Two things to note:

  1. In the BTP Launchpad, you need to add base URL (something like ‘/6933944e-429d-4c98-8fb1-24d04de767f7.userapiservice.demouserapi/~010821071004+0000~‘) before the URL you’re actually calling. Without the base URL, the call will fail with Not Found (404) error. This is not specific to User API, but applies to any other URLs.
  2. In the local environment User API is not available so I’ve set mock data just to check if the view is correctly displayed.

I’ve created a simple view to display user info.

 <mvc:View controllerName="demo.userapi.controller.MainView"
  displayBlock="true"
  xmlns="sap.m"
	xmlns:l="sap.ui.layout"
	xmlns:f="sap.ui.layout.form"  
  xmlns:mvc="sap.ui.core.mvc">
  <App id="idAppControl" >
    <pages>
      <Page title="{i18n>title}">
        <content>
          <VBox class="sapUiSmallMargin">
            <f:SimpleForm id="SimpleFormDisplay354"
              editable="false"
              layout="ResponsiveGridLayout"
              title="User Info"
              labelSpanXL="3"
              labelSpanL="3"
              labelSpanM="3"
              labelSpanS="12"
              adjustLabelSpan="false"
              emptySpanXL="4"
              emptySpanL="4"
              emptySpanM="4"
              emptySpanS="0"
              columnsXL="1"
              columnsL="1"
              columnsM="1"
              singleContainerFullSize="false" >
              <f:content>
                <Label text="First Name" />
                <Text text="{userInfo>/firstname}" />
                <Label text="Last Name" />
                <Text text="{userInfo>/lastname}" />
                <Label text="Email" />
                <Text text="{userInfo>/email}" />
                <Label text="Display Name" />
                <Text text="{userInfo>/displayName}" />                                                
              </f:content>
            </f:SimpleForm>
          </VBox>
        </content>
      </Page>
    </pages>
  </App>
</mvc:View>

 

4. Deploy to the Cloud Foundry

Build and deploy the MTA project to the Cloud Foundry with the command below.

npm run deploy

After successful deployment, add the app to the Launchpad.
You can refer to my previous blog (Step6. Configure the Launchpad) for how to do this.
The app will show logged-in user info as below.

 

References

Document of User API Service
SAP Approuter – User API Service by Dries Van Vaerenbergh
SAP Tech Bytes: Approuter User API Service by DJ Adams

Assigned tags

      12 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Ali Asad
      Ali Asad

      Hi Mio Yasutake,

      Thanks for sharing.

      Recently implemented this, after declaring the route in xs-app.json, one can declare a datasource and model in manifest.json and then bind it directly in the View. Just like any other model. 

      Author's profile photo Mio Yasutake
      Mio Yasutake
      Blog Post Author

      Thanks for your comment.

      Yes, if you declare a model in manifest.json you don't have to manipulate the base path on your own.

      Author's profile photo Michael Flucher
      Michael Flucher

      Hi Mio Yasutake,

      thanks for the Tutorial.

      I currently use your provided method to access user information, but I also need some custom added assertion attributes from the IdP. Dou you know if that is also possible somehow?

      Author's profile photo Mio Yasutake
      Mio Yasutake
      Blog Post Author

      Hi Michael Flucher,

      Thanks for your comment!

      I haven't tried it myself, but the following links might be relevant.

      https://blogs.sap.com/2020/07/24/mapping-of-saml-attributes-with-xsuaa-jwt-in-cloud-foundry/

      https://answers.sap.com/questions/13354661/how-to-access-saml-attributes-through-request-obje.html

      Author's profile photo Michael Flucher
      Michael Flucher

      Thanks, the first link was very helpful

      Author's profile photo Mateo Suite
      Mateo Suite

      Mio Yasutake

      Many thanks for the information.

      We have created a React App based on the blog below:

      https://blogs.sap.com/2021/07/05/react-development-with-sap-business-application-studio

      Would your approach work as well to retrieve the user credentials?

      Regards,

      C.

      Author's profile photo Mio Yasutake
      Mio Yasutake
      Blog Post Author

      Hi Mateo Suite,

      Thanks for reading and commenting.

      I think this approach works for React App too.

      You can make http request to the endpoint `/user-api/currentUser` inside the application logic.

       

       

       

      Author's profile photo Mateo Suite
      Mateo Suite

      Mio Yasutake

      Many thanks for your response.

      Could you please clarify further how the base path of the URL is formed?

      Is it based on the URL of the HTML5 application? For example, if my HTML5 app url is as follows:

      https://8dee05abtrial.launchpad.cfapps.eu10.hana.ondemand.com/32542353-e153-4124-acda-b7a158c320bb.IntegrationAdvisoryWizard.IntegrationAdvisoryWizardModule-1.0.0/index.html

      What would be the API call endpoint?

      Thanks!

      C.

      Author's profile photo Mio Yasutake
      Mio Yasutake
      Blog Post Author

      I guess the base path will be:

      https://8dee05abtrial.launchpad.cfapps.eu10.hana.ondemand.com/32542353-e153-4124-acda-b7a158c320bb.IntegrationAdvisoryWizard.IntegrationAdvisoryWizardModule-1.0.0/

      You can open a new browser while the app is running, and test if the following request works.

      https://8dee05abtrial.launchpad.cfapps.eu10.hana.ondemand.com/32542353-e153-4124-acda-b7a158c320bb.IntegrationAdvisoryWizard.IntegrationAdvisoryWizardModule-1.0.0/user-api/currentUser

       

       

      Author's profile photo Mateo Suite
      Mateo Suite

      Many thanks Mio Yasutake

      Unfortunately, I am getting "File not found".

      Any thoughts?

      Regards,

      C.

      Author's profile photo Mio Yasutake
      Mio Yasutake
      Blog Post Author

      Hi Mateo Suite,

      I followed the tutorial you mentioned, and was able to get user information in the browser.

      Make sure to include the following part in /public/xs-app.json.

        "routes": [
          {
            "source": "^/user-api/currentUser$",
            "target": "/currentUser",
            "service": "sap-approuter-userapi"
          },  

      After the app is deployed to the Launchpad, I entered the following URL to the browser and could see my data.

      https://b736177ctrial.launchpad.cfapps.eu10.hana.ondemand.com/d37c6155-ebd4-462e-8c30-3139dea9eeaa.reactdemoservice.reactsample-1.0.0/user-api/currentUser

       

      With the following code you should be able to get user data.

      I'm not familiar with React, so not sure how to display this data in the UI...

      import axios from "axios";
      
      const baseURL = "user-api";
      
      const instance = axios.create({
        baseURL
      });
      
      export const getUserData = async () => {
        const { data } = await instance.get("/currentUser");
        return data;
      };

       

      Regards,

      Mio

      Author's profile photo Mateo Suite
      Mateo Suite

      Problem sorted! Many thanks!