Technical Articles
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
- Generate an UI5 project
- Add a route to xs-app.json
- Write controller code to get user info
- 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:
- 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. - 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
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.
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.
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?
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
Thanks, the first link was very helpful
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.
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.
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.
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
Many thanks Mio Yasutake
Unfortunately, I am getting "File not found".
Any thoughts?
Regards,
C.
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.
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...
Regards,
Mio
Problem sorted! Many thanks!
Hi Mio Yasutake.
I followed your post, in order to obtain the information of the user who logs into BTP, but when using it in the SAP BAS locally, the following message appears.
Could it be that I am missing something?
Could it be that I am not following the tutorial well?
Or will this solution be visible when deployed to an app?
I hope you can help me
Regards.
ebz