How to get authenticated user information with CAP in three different ways – Setup project for development


Prerequisites

To follow-up with this blog post you must complete the following prerequisites:

  • Read the Series Introduction post;
  • Create an SAP BTP Trial Account following this tutorial;
  • Setup SAP Business Application Studio in your SAP BTP trial following this tutorial;
  • In your SAP Business Application Studio, create a dev space for Full-Stack development.

Access SAP Business Application Studio

We are going to start by accessing the selected IDE for development (in this case, SAP Business Application Studio).

Access your trial subaccount

Figure%201%20-%20BTP%20trial%20access

Figure 1 – BTP trial access

On the left-hand side expand Services and click on Instances and Subscriptions

Figure%202%20-%20Instances%20and%20Subscriptions

Figure 2 – Instances and Subscriptions

On the right, under Subscriptions, click on the small icon next to the SAP Business Application Studio subscription to go to the application

Figure%203%20-%20Open%20Business%20Application%20StudioFigure 3 – Go to Application

Start your previously created Dev Space by clicking on the Start Icon on the right

Figure%204%20-%20Start%20Dev%20Space

Figure 4 – Start Dev Space

After the Dev Space has started (status RUNNING), go into it by clicking on the Space Name

Figure%205%20-%20Go%20into%20Dev%20Space

Figure 5 – Go into Dev Space

Login to Cloud Foundry

Before starting the development, you need to make sure to be properly logged in to the Cloud Foundry environment on your BTP subaccount.

From the top menu, click on View and select Find Command…

Figure%206%20-%20Find%20Command

Figure 6 – Find Command

In the Find Command dropdown, search for CF: Login to Cloud Foundry and select it

Figure%207%20Login%20to%20Cloud%20Foundry

Figure 7 Login to Cloud Foundry

Confirm the Cloud Foundry endpoint, by pressing Enter

Figure%208%20-%20Cloud%20Foundry%20endpoint

Figure 8 – Cloud Foundry endpoint

Enter the e-mail address you have used to create your trial account and press Enter

Figure%209%20-%20Enter%20e-mail%20address

Figure 9 – Enter e-mail address

Enter the password you have used to create your trial account and press Enter

Figure%2010%20-%20Enter%20password

Figure 10 – Enter password

Select your trial organization and press Enter

Figure%2011%20-%20Select%20organization

Figure 11 – Select organization

Select your Cloud Foundry dev space and press Enter

Figure%2012%20-%20Select%20Cloud%20Foundry%20Space

Figure 12 – Select Cloud Foundry space

Click on the small notifications icon in the bottom right corner to view the login notifications to make sure the login has been successful

Figure%2013%20-%20Confirm%20successful%20login

Figure 13 – Confirm successful login

Create the CAP Project

Now it’s time to create the CAP Project.

From the top menu, click on Terminal and select New Terminal

Figure%2014%20-%20New%20Terminal

Figure 14 – New Terminal

In the terminal window at the bottom, type cd projects and press Enter. The terminal should look like this:

Figure%2015%20-%20Terminal%20at%20projects%20folder

Figure 15 – Terminal at projects folder

Now type cds init user-info and press Enter. The output should look like this:

Figure%2016%20%u2013%20Project%20initialization

Figure 16 – Project initialization

Notice that user-info is the project and application name and also the project folder name. Now, let’s open the project as a workspace.

From the top menu, click on File and select Open Workspace…

Figure%2017%20-%20Open%20Workspace

Figure 17 – Open Workspace

In the dialog, select the user-info folder under projects and the VS Code Workspace (*.code-workspace) from the Format dropdown, then click Open

Figure%2018%20%u2013%20Set%20Workspace

Figure 18 – Set Workspace

SAP Business Application Studio will restart and, after a few seconds, you should see the following structure at the bottom of the left-hand side pane:

Figure%2019%20%u2013%20Project%20Structure

Figure 19 – Project Structure

As the Dev Space has restarted, execute the procedure to open a New Terminal again.

Create an Index Page

To test each method for getting the authenticated user information, let’s create an index page (index.html) which will represent our application’s basic front-end (UI).

In a new Terminal, type the following commands pressing Enter after each one.

mkdir app/root
touch app/root/index.html

The index.html file will be created under the app/root folder:

Figure 20 – index.html created

Now, open-up that file and copy & paste the following content into it:

<!DOCTYPE html>
<html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>User Info Demo App</title> </head> <body> Three differnt ways for getting the authenticated user info: <ul> <!-- TODO: Add the links to each respective method --> <li>1. Directly from the UI (HTML5 app)</li> <ul> <li>1a. Using the <b>/currentUser</b> endpoint</li> <li>1b. Using the <b>/attributes</b> endpoint</li> </ul> <li>2. Using the CAP request object</li> <li>3. Using the XSUAA API</li> </ul> </body>
</html>

Create a Standalone AppRouter

To get user information, first, the user must be authenticated into your application. For that to happen the authentication flow must be completed. This flow follows the OAuth 2.0 protocol and is taken care by the so-called AppRouter. So, let’s add it to the project!

We will start by creating a package.json file into the app folder.

In the Terminal type these two command pressing Enter after each one:

cd app
npm init

For the second one provide the following information:

  • package name: app
  • version: 1.0.0
  • description: User Info Demo App
  • entry point: index.html
  • test command: node node_modules/@sap/approuter/approuter.js
  • author: <your name>
  • license: ISC

Leave all the other parameters blank.

Open-up the newly created package.json under the app folder and replace the “test” script by “start“. Your final content should look like this:

Figure%2021%20-%20app/package.json%20content

Figure 21 – app/package.json content

The next step is to install the AppRouter node package, by running the following command:

npm install @sap/approuter

OK, so, now the AppRouter should know what’s the application entry point and which routes it should map to such application. For that it uses a configuration file named xs-app.json. Therefore, we need to create that file under the app folder by running the following command:

touch xs-app.json

Now, open-up that file and copy & paste the following JSON content into it:

{ "welcomeFile": "index.html", "authenticationMethod": "route", "routes": [ { "source": "/user-info/(.*)", "destination": "srv-api", "csrfProtection": true, "authenticationType": "xsuaa" }, { "source": "/(.*)", "localDir": "root", "authenticationType": "xsuaa" } ]
}

For now, in this configuration, we will just map the root folder as the location for static content such as de index page (second route) and the CAP backend service as a destination named “srv-api” (although you might not need it if you don’t want to experiment with any of the two approaches based on it – request object or XSUAA API). A new route will be added in the instructions of the blog post regarding the first approach.

Create an XSUAA Service Instance

We shall remember that, in Cloud Foundry, security (meaning authentication and authorization) is governed by the UAA (User Account and Authentication) mechanics which in SAP BTP is implemented by the XSUAA service (Authorization and Trust Management Service).

This means that only having the AppRouter properly set up in the application is not enough to achieve the complete OAuth 2.0 authentication flow as it depends on the XSUAA service for that.

Therefore, we need to create an XSUAA service instance on BTP, but, first, it will require a configuration file that’s provided upon instance creation. That file is named xs-security.json and it will be created under the project’s root folder.

In the Terminal type these two commands pressing Enter after each one:

cd ..
touch xs-security.json

Now, open-up that file and copy & paste the following JSON content into it:

{ "xsappname": "user-info", "tenant-mode": "dedicated", "description": "Security profile of User Info Demo App", "scopes": [ { "name": "uaa.user", "description": "UAA" } ], "role-templates": [ { "name": "Token_Exchange", "description": "UAA", "scope-references": [ "uaa.user" ] } ], "oauth2-configuration": { "redirect-uris": [ "https://*.hana.ondemand.com/**", "https://*.applicationstudio.cloud.sap/**" ] }
}

The uaa.user scope associated to the Token_Exchange role template is required to perform the OAuth 2.0 authentication flow executed by the approuter. Basically, before loading the HTML5 application (in this case just the index.html page) the router authenticates the user logged in to SAP BTP via OAuth 2.0 and gets a JWT (JSON Web Token) which is, then, forwarded to the HTML5 application and, from there, to the CAP service, making sure that only authenticated users have access to the application.

The “redirect-uris” in the “oauth2-configuration” is just a list of allowed endpoints (hosts and paths which can use wildcards) to be used as callbacks to which the OAuth flow redirects when authentication is completed. URIs that are not listed are considered “invalid” by the OAuth flow, so the above configuration makes sure that the authentication flow is well executed either when the application is deployed to Cloud Foundry (*.hana.ondemand.com) as well as when running locally on Business Application Studio (*.applicationstudio.cloud.sap).

Now, we can create the XSUAA service instance by running the command below:

cf create-service xsuaa application user-info-xsuaa -c xs-security.json

This should be the expected outcome:

Figure%2022%20-%20XSUAA%20service%20instance%20created

Figure 22 – XSUAA service instance created

Bind the XSUAA Service Instance to the AppRouter

Upon successful creation of the service instance, on the left-hand pane of BAS click on the Cloud Foundry icon (small light bulb), then on the refresh button at the top right of the pane.

The newly created instance should be displayed at end of the list, like demonstrated below:

Figure%2023%20%u2013%20Newly%20created%20service%20instance

Figure 23 – Newly created service instance

Right click on the user-info-xsuaa service instance and select “Bind service to a locally run project” and, then, in the dialog, make sure the app folder is selected and click on the “Select folder for .env file” button.

Figure 24 – Select app folder

Click again on the Explorer icon in the left-hand pane. You should see the .env file that has been created like demonstrated below:

Figure 25 – .env file for services binding

Now, we need to rename that file to default-env.json and transform its contents into JSON format (as it’s just defining a regular environment variable called VCAP_SERVICES which is not in the expected JSON format), like demonstrated below:

Figure 26 – Rename .env and adjust to JSON format

NOTE: if you do not intend to experiment with any of the backend service approaches (request object or XSUAA API) you can safely skip all the next steps.

Configure the Backend (CAP) Service Destination

You may recall that, in the xs-app.json configuration, the first route which was added to it is pointing to a destination named “srv-api“, right? Therefore, the AppRouter needs to read that destination’s configuration and it will look for it in the same default-env.json file, but in an environment variable (key) named destinations apart from the VCAP_SERVICES.

To create such configuration just add the following line right before the “VCAP_SERVICES” in the default-env.json file:

 "destinations" : [{ "name" : "srv-api", "url" : "http://localhost:4004", "forwardAuthToken" : true }],

After the modification, your default-env.json file should look like this:

Figure%2027%20-%20Destination%20added%20to%20default-env.json

Figure 27 – Destination added to default-env.json

You may have noticed that the URL points to the locally run CAP service (http://localhost:4004) and the router should forward the authentication token (JWT) to it after execution of the OAuth 2.0 flow.

One important thing to mention is that everything that’s configured in the default-env.json is only effective in a local development environment as this file is not deployed to BTP with the application and shall not be included in version control repositories (such as Git) as it holds sensitive information like credentials.

You can learn more about project-specific configurations (which this file is part of) in this page from the CAP official documentation.

Create the Service Definition

The second and third approaches to get the authenticated user information from this blog posts series are done in the backend service of the solution, meaning the CAP service.

Therefore, the first thing that’s necessary is to create the usual CDS service definition in the “srv” folder. For that, just run the command below in the Terminal:

touch srv/user-info-service.cds

Open-up the user-info-service.cds file, then copy and paste the following content into it:

service UserInfoService @(path : '/user-info', requires: 'authenticated-user') { function userInfo() returns String; // using req.user approach (user attribute - of class cds.User - from the request object) function userInfoUAA() returns String; // using the XSUAA API
}

In the CAP service, we’ll not actually define any OData entities (as usually expected), but just two functions (one for each approach). You may notice that the service is being served in the “/user-info” path and requires authentication (as expected).

Create the Function Handler

Now, we need to create a “skeleton” for the implementation of the two functions described in the service definition. In the Terminal, run the command:

touch srv/user-info-service.js

Open-up the user-info-service.js file, then copy and paste the following content into it:

module.exports = cds.service.impl(async function () { // using req.user approach (user attribute - of class cds.User - from the request object) this.on('userInfo', req => { return ""; }); // using the XSUAA API this.on('userInfoUAA', async () => { return ""; });
});

As you can see, in this “skeleton”, both functions are just returning an empty string, thus waiting for the corresponding implementation of each approach.

Install Project Dependencies

Both approaches will require the CAP backend service to handle security (basically the JWT – JSON Web Token – provided after authentication via XSUAA), thus the need to install the appropriate dependencies for it to accomplish that goal.

In the Terminal, run the following commands:

npm install @sap/xssec
npm install passport

And to install all other dependencies from the generated package.json just run:

npm install

Bind the XSUAA Service Instance to the CAP Service

The binding of the XSUAA service instance to the CAP service is slightly different from the approach taken to bind it to the AppRouter. For a local development environment, CAP leverages what’s called hybrid testing approach through the cds bind command.

You can learn more about XSUAA in a Hybrid Setup in this page from the official CAP documentation.

In the Terminal, run the following command:

cds bind uaa --to user-info-xsuaa:key --kind xsuaa

This should be the expected outcome:

Figure 28 – XSUAA service bound to CAP project

The command generates a new configuration file in the project: cdsrc-private.json.

Figure%2029%20-%20cdsrc-private.json%20generated

Figure 29 – cdsrc-private.json generated

Now, we need to make an enhancement to this file for the service authentication to work properly. So, open it and add the following block right after the block “uaa” : { … }:

 , "auth": { "kind": "jwt-auth" }

After that modification your cdsrc-private.json file should look like this:

Figure%2030%20-%20Modified%20cdsrc-private.json

Figure 30 – Modified cdsrc-private.json

Notice that the [Hybrid] feature, defined at the very beginning, states that the configuration must emulate the VCAP_SERVICES environment variable. However, it does not dismiss the usage of the default-env.json file.

So, make sure to copy that file from the app folder to the root folder of your project (same folder as the cdsrc-private.json file):

Figure%2031%20-%20default-env.json%20together%20with%20cdsrc-private.json

Figure 31 – default-env.json together with cdsrc-private.json

And with that, we completed the setup of the project to start the development of the different approaches to the get the authenticated user information with CAP and we are now good to go!

Conclusion

After having gone through the steps of this blog post you should have successfully initialized and prepared your CAP Project getting ready ready to start the application development. The next step would be to try one of the three different approaches for getting the authenticated user information proposed in this blog posts series.

Please, do not hesitate to submit your questions in SAP Community through the Q&A tag link: https://answers.sap.com/index.html

Other blog posts in this series

  • Directly from the UI (HTML5 app)
  • Using the CAP request object
  • Using the XSUAA API