Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
joachimvanpraet
Active Participant
Recently we started our first CAP nodejs project.
Initially we used the SAP Web IDE, but we ran into the problem that we were not able to test our service with authentication quickly. We always had to deploy the service first, and that was taking a lot of time.

So we decided to move our developments locally and start using visual studio code for CAP developments. To test our service we want to use our data, destinations and authorizations from our Cloud foundry services.

In this blog post I will describe how you can use the XSUAA service on cloud foundry to be able to use authentication in your local environment.

Prerequisites


To be able to test the things I'll describe here you have to install some tools ...

cloud foundry cli


This command line tool is able to get information from your cloud foundry account.
Find download and installation information here:

https://docs.cloudfoundry.org/cf-cli/install-go-cli.html

SAP Cloud MTA Build Tool


This command-line tool builds a multitarget application archive file from the artifacts of an MTA project.

Because this tool is using makefile, Windows user should first install Chocolatey and GNU Make.

https://chocolatey.org/install

https://chocolatey.org/packages/make

When make is installed, you are able to install the MTA Build tool:
npm install -g mbt

More information here:

https://sap.github.io/cloud-mta-build-tool/

Example project


Through this blog post you can use my example project on github.
You can just deploy this example on your trial account and test it.

https://github.com/jowavp/SAP-CAPM-Nodejs-Authorisation-example

Clone the project to your PC and try to deploy it to your cloud foundry account.
git clone https://github.com/jowavp/SAP-CAPM-Nodejs-Authorisation-example
cd SAP-CAPM-Nodejs-Authorisation-example\

in your command you have to log on to your cloud foundry account. Just enter "cf login" in your shell and provide the correct information.
cf login
API endpoint: https://api.cf.eu10.hana.ondemand.com

Email> joachim.vanpraet@****.com

Password>
Authenticating...
OK

Select an org (or press enter to skip):
1. S0003564161trial_trial

Org> 1
Targeted org S0003564161trial_trial

Targeted space dev

API endpoint: https://api.cf.eu10.hana.ondemand.com (API version: 2.141.0)
User: joachim.vanpraet@****.com
Org: S0003564161trial_trial
Space: dev

then you can deploy the project! just run
npm run deploy

this command will build the MTA archive and start deployment on cloud foundry. Time to take a coffee, this can take some time 🙂

If the project is deployed, you can test it by opening the url of the approuter module in our project.
To get this url, just run 'cf apps'
> cf apps
Getting apps in org S0003564161trial_trial / space dev as joachim.vanpraet@****.com...
OK

name requested state instances memory disk urls
CAPMAuthorisation-approuter started 1/1 256M 256M s0003564161trial-trial-dev-capmauthorisation-approuter.cfapps.eu10.hana.ondemand.com
CAPMAuthorisation-srv started 1/1 512M 256M s0003564161trial-trial-dev-capmauthorisation-srv.cfapps.eu10.hana.ondemand.com

you'll see a table of all applications running on your cloud foundry environment. The last column is the url, if you open this url in a brower, the approuter will route you to the service.

This should be the response:
{
"@odata.context": "$metadata#User(username)",
"@odata.metadataEtag": "W/\"V7/t5WepB4qxHRqSBCe3fnSl+gQ4dVwCnhtBLUGyukQ=\"",
"value": [
{
"username": "joachim.vanpraet@****.com"
}
]
}

Running locally


Let's get this thing running on our local environment. To know which user is logged on we need the authentication token (in cloud foundry this is the JWT Token) injected in the service. Injecting this token is done by the approuter. The approuter will get the token from the uaa service and add it to the the Authorization header in the request to the service.

The secret for achieving this with minimal effort is in using default-services.json and default-env.json files. These files are included in the .gitignore file because they contain secrets you don’t want to share with the world.

The Service


The source files of the service are located in the srv folder. When you open the service.cds you can see the following:

 
@impl:'service.js'
@cds.query.limit: 100
service CapmAuthUserService @(requires:'authenticated-user'){
entity User {
key username : String;
}
}

Important piece of code here is the @(requires:'authenticated-user') this will only allow authenticated users to access theservice.

open the shell in the root directory of the project and install all npm package
npm install

After the installation of the nod modules, we start the service with the following command:
npm run start:local

This will start the service locally on https://localhost:4004

If we follow this link, we will get a 403 response ‘Forbidden:
{"error":{"message":"Forbidden"}}

This is due to the fact that we’ve annotated the CDS service with @(requires:’authenticated-user’)

Keep this service running, don't close your shell.

Open a new shell window for the following steps where you will inject a JWT token into the service.
As mentioned earlier, this is done by the approuter.

Approuter


The approuter is configured in the ‘approuter’ folder in the project. xs-app.json
{
"welcomeFile": "/capm-auth-user",
"authenticationMethod": "route",
"logout": {
"logoutEndpoint": "/do/logout"
},
"routes": [{
"source": "^/(.*)$",
"target": "$1",
"authenticationType": "xsuaa",
"scope": "$XSAPPNAME.user",
"destination": "srv_api",
"csrfProtection": false
}]
}

We’ve set authenticationMethod to “route” so we decide in each route which authentication type we want to use. There is only one route that will proxy all requests to the srv_api destination and uses xsuaa for the authentication.

Let’s first check the mta.yaml file for this module in the root folder of the project.
  - name: CAPMAuthorisation-approuter
type: approuter.nodejs
path: approuter
parameters:
disk-quota: 256M
memory: 256M
requires:
- name: CAPMAuthorisation-uaa
- name: srv_api
group: destinations
properties:
forwardAuthToken: true
name: srv_api
strictSSL: false
url: '~{url}'

In Cloud Foundry this approuter module requires 2 services:

  • The CAPMAuthorisation-uaa service (which is the uaa service)

  • The srv_api destination (which is provided by our CAPMAuthorisation-srv module)


In the srv_api destination, we set forwardAuthToken to true. This will forward the JWT token from the approuter to the destination.

If we want to run this approuter module locally, we must install the node modules for this module. Go into the approuter directry
cd approuter

Install the node modules
npm install

Run the approuter
npm run start

This will fail, because the approuter is not able to find the destination srv_api. When you deploy this app to cloud foundry, the approuter will find the srv_api destination because it is defined in the mta.yaml file.
C:\Users\vanprjo\git\capm-nodejs-authorisations\approuter\node_modules\@sap\approuter\lib\utils\JsonValidator.js:30    
throw new VError('%s%s: %s',

VError: xs-app.json/routes/0: Format validation failed (Route references unknown destination "srv_api")

We have to define this destination for our local environment.
create a default-env.json file in the approuter folder.
{
"destinations": [
{
"name": "srv_api",
"url": "http://localhost:4004",
"forwardAuthToken": true,
"strictSSL": false
}
]
}

This will create the destination like we did in the mta.yaml file, but this will point to http://localhost:4004. This is the address where our service is running.

Let’s try to start the approuter again …
npm run start

This will again fail because you need a uaa service to authenticate yourself.
C:\git\capm-nodejs-authorisations\approuter\node_modules\@sap\approuter\lib\configuration.js:64
throw new Error('No UAA service found');
Error: No UAA service found

We can reuse the authentication service of our CF account. Let’s first search for the credentials we need for this service.
run cf apps



Get the environment variables for the approuter app
cf env CAPMAuthorisation-approuter

We will only focus on the parameters in System-Provided. There we see a service xsuaa. Copy the values in credentials.



Create a default-services.json file in the approuter folder where we will set the credentials to the UAA service.

This is the content of default-services.json.
{
"uaa": {
"apiurl": "https://api.authentication.eu10.hana.ondemand.com",
"clientid": "<your_clientid>",
"clientsecret": "<your_clientsecret>",
"identityzone": "<your_identityzone>",
"identityzoneid": "<your_identityzoneid>",
"sburl": "https://internal-xsuaa.authentication.eu10.hana.ondemand.com",
"tenantid": "<your_tenantid>",
"tenantmode": "dedicated",
"uaadomain": "authentication.eu10.hana.ondemand.com",
"url": "https://<your_account>.authentication.eu10.hana.ondemand.com",
"verificationkey": "-----BEGIN PUBLIC KEY-----<public key>-----END PUBLIC KEY-----",
"xsappname": "<your_appname>"
}
}

We also need to copy this file to the root directory of our project because in the service, we need to validate the JWT token. But I found out that in the @Sap/cds library they are looking for xsuaa service, so we have to rename uaa to xsuaa … (only rename the service in the default-services.json file in the root directory of the project)
{
"xsuaa": {
"apiurl": "https://api.authentication.eu10.hana.ondemand.com",
"clientid": "<your_clientid>",
"clientsecret": "<your_clientsecret>",
"identityzone": "<your_identityzone>",
"identityzoneid": "<your_identityzoneid>",
"sburl": "https://internal-xsuaa.authentication.eu10.hana.ondemand.com",
"tenantid": "<your_tenantid>",
"tenantmode": "dedicated",
"uaadomain": "authentication.eu10.hana.ondemand.com",
"url": "https://<your_account>.authentication.eu10.hana.ondemand.com",
"verificationkey": "-----BEGIN PUBLIC KEY-----<public key>-----END PUBLIC KEY-----",
"xsappname": "<your_appname>"
}
}

Let’s try to start the approuter again …
npm run start

The approuter is running on port 5000
Note:

It is important to install node modules "passpor"t and "@sap/xssec" in the root folder of the project. Otherwise the injected token will be ignored in the CDS service.

The result


let’s go to http://localhost:5000

TADAA …

Now you have the logon screen of your account.
Enter your credentials and when you navigate to the entity User you should be able to see the current userid.



As you can see running nodejs based cloud foundry application on your own environment is very easy. The new SAP Application studio (which is available as beta feature at the moment) should also support this approach for developing and testing CAP nodejs application.

kr,

Joachim
13 Comments
Labels in this area