Skip to Content
Technical Articles
Author's profile photo Balbino Soares Ferreira Filho

Understanding security approaches in SAP CAP using XSUAA in node.js flavor and MTA.

In this blog post, my intent is to try to explain more about authentication strategies on SAP Cloud Platform, using Sap Cloud Application Programming Model with Node.js and Multi-Target Application Deployment.

In this link, you can found a guide about authentication while accessing CDS services in Node.js applications. https://cap.cloud.sap/docs/node.js/authentication#jwt

First, I want to explain a little bit about the authentication flow and the project structure.

Multi-Target Application Project

Normally, an application on SAP Cloud Platform will consist of several parts, that will be deployed as separate applications. Each one of these applications will be a module of your project. This structure is the base of the Multi-Target Application Model.

In this model, we have a deployment descriptor file, the mta.yaml. This file is responsible to define each part of your project, the resources necessary to execute this project, and the connection link between their modules.

In this module, we have a mtar file with the entire project and the deployment descriptor file defines how the resources and services must be created and allocated.

To be able to build your project with a multi-target application and deploy him using cloud foundry command line (CF CLI), some tools and steps will be necessary:

  1. If you don’t have a Cloud Foundry Subaccount on SAP Cloud Platform yet, create your Trial Account;
  2. The Cloud MTA Build Tool (MBT) is installed;
  3. Download and install the cf command-line client for Cloud Foundry;
  4. Install MultiApps CF CLI Plugin;
  5. Log on to Cloud Foundry, using cf login to your trial account;

To build an MTA application you will need to execute this command. You can define a script in your package.json if you prefer.

cds build/all --clean && mbt build -p=cf

User authentication in the MTA Project

In SAP Cloud Platform we have a service that is responsible to do the authentication stuff, this service is the XSUAA service (Authorization & Trust Management). So, to use authentication in your application you will need to create a service instance of the XSUAA service and link this service to your application’s services.

In an MTA project, we can do it in mta.yaml file. See the example below, where we defined the resource to be allocated using the XSUAA service.

 

##############  RESOURCES  ##################################      
resources:
  - name: school-db-hdi-container
    parameters:
      service: hanatrial
      service-plan: hdi-shared  
    type: com.sap.xs.hdi-container
    properties:
      hdi-container-name: ${service-name}
### XSUAA service instance      
  - name: school-xsuaa
    parameters:
      path: ./xs-security.json  
      service: xsuaa    
      service-plan: application
      service-keys: 
        - name: school-xsuaa-key      
    type: com.sap.xs.uaa    
############################################################    

Authentication Flow

In general, the entire application will be formed of a database module, responsible for the database content, a module for the service layer, in our case this module will be a Node.js application and a finally, a user interface module that will be the entry point of the entire application.

All application that uses an XSUAA service needs a module responsible for the application router. Generally, this module is the “app” module or the UI module and it will be the entry point of your application. But even your application doesn’t have a UI interface, you will need to create an app to be responsible for the application router.

When your business user accesses the application UI using the browser, the application router redirects the browser to the UAA service, where your user needs to authenticate. After successful authentication, the UAA sends the browser back to applications router with an OAuth authorization code. Now the application router sends this authorization code to the UAA directly, this time not by browser, to exchange it into on OAuth access token. If the access token is obtained successfully, your users will be logged on to the UI part of the application. This token needs to be passed to the Node.js application part, to grant the privileges defined in CDS service.

To enable your UI to pass this authentication on to the node.js application part, you need to ensure that the destination to your node.js application part is configured such that the access token is sent. It is configured in mta.yaml file by the property in the “destination” group of the app-router. The property is forwardAuthToken”: true.

See below the configuration of the app-router in mta.yaml file.

#### App Router used to authentication          
  - name: school-app-router
    type: nodejs
    path: app
    build-parameters:
      ignore: ["node_modules/"]    
    parameters:
       disk-quota: 256M
       memory: 256M
    requires:
      - name: school-xsuaa
      - name: srv_api
        group: destinations
        properties:
          forwardAuthToken: true
          strictSSL: false
          name: srv_api
          url: ~{url}

 

The same XSUAA service needs to be bound to the SRV app and to the app-router, in the mta.yaml. See the “requires” part on the SRV app configuration.

#### The SRV Module is the backend of application, It will be started      
  - name: school-srv
    type: nodejs
    path: srv
    build-parameters:
      ignore: ["node_modules/"]    
    parameters:
      memory: 256M
      disk-quota: 256M
    provides:
      - name: srv_api
        properties:
          url: ${default-url}
    requires:
      - name: school-db-hdi-container
      - name: school-xsuaa

As said earlier, is necessary to include and configure the app-router in your application even if you only have a backend service. But If you have a UI app in your project you can configure the router in this UI module.

The important file in this part is the xs-app.json responsible to create the routes and authentication method that will be used. In the example above see that access in any URL will be redirected to XSUAA because the authentication method is set to the route. After the authentication is successful the route will redirect to the destination srv_api, which is the service defined in mta.yaml file.

Below an example of the xs-app.json file.

{
    "authenticationMethod":"route",
    "routes": [
        {
            "source": "^/(.*)$",
            "target": "$1",
            "authenticationType": "xsuaa",
            "destination": "srv_api",           
            "csrfProtection": false
            
        }
    ]
}

Step to Step to configure XSUAA in your application.

For this flow works as expected is necessary to do some configurations in your application. And this can be done by the following steps:

You can see an entire project of example in my GitHub: https://github.com/balbinosoares/school-cap.

  1. In your service.cds file define the annotations to require the authentication with a specified role, for example in my AdminServices, it requires the role admin. For more information about this topic check https://cap.cloud.sap/docs/guides/authorization.
    service AdminService  @(requires:'admin'){​
  2. Generate the xs-security.json file. This file defines the role-template of the application and is used by the XSUAA service. It can be generated by cds compile, using as reference the annotations defined in the services model.
    cds compile srv/ --to xsuaa > .xs-security.json
    {
      "xsappname": "school",
      "tenant-mode": "dedicated",
      "scopes": [
        {
          "name": "$XSAPPNAME.admin",
          "description": "admin"
        }
      ],
      "attributes": [],
      "role-templates": [
        {
          "name": "admin",
          "description": "generated",
          "scope-references": [
            "$XSAPPNAME.admin"
          ],
          "attribute-references": []
        }
      ]
    }
    
  3. Install the modules that are required at runtime to authenticate the user and read the token. You need to install these modules both in the root of your project and in the SRV folder of your project.
    npm install --save passport @sap/xssec @sap/xsenv

    Below you can see the Package.json of the SRV module.

    {
        "name": "school-srv",
        "description": "Generated from ../package.json, do not change!",
        "version": "1.0.0",
        "dependencies": {        
            "@sap/cds": "^3.21.2",
            "@sap/xsenv": "^2.2.0",
            "@sap/xssec": "^2.2.5",
            "express": "^4.17.1",
            "hdb": "^0.17.1",
            "passport": "^0.4.1"
        },
        "engines": {
            "node": "^8.9",
            "npm": "^6"
        },
        "devDependencies": {},
        "scripts": {
            "postinstall": "npm dedupe && node .build.js",
            "start": "node ./node_modules/@sap/cds/bin/cds.js serve gen/csn.json",
            "watch": "nodemon -w . -i node_modules/**,.git/** -e cds -x npm run build"
        },
        "cds": {
            "requires": {
                "db": {
                    "kind": "hana",
                    "model": "gen/csn.json"
                }
            },
            "auth": {
                "passport": {
                    "strategy": "JWT"
                }
            }
        }
    }
    

    And next, the Package.json of the top-level package.

    {
      "name": "school",
      "version": "1.0.0",
      "description": "A project to pratice and study more about SAP Cloud Application Programming Model. ",
      "repository": "https://github.com/balbinosoares/school-cap.git",
      "license": "Apache-2.0",
      "dependencies": {
        "@sap/cds": "^3.21.x",
        "@sap/hana-client": "^2.4.182",
        "@sap/xsenv": "^2.2.0",
        "@sap/xssec": "^2.2.5",
        "express": "^4.17.1",
        "hdb": "^0.17.1",
        "passport": "^0.4.1"
      },
    
  4. Create the App-router of your application.
    • Create an app folder
    • Create a file: Package.json in /app
      {
        "name": "approuter",
        "dependencies": {
          "@sap/approuter": "latest"
        },
        "scripts": {
          "start": "node app.js"
        }
      }
      ​
    • Create an xs-app.json file.
      {
          "authenticationMethod":"route",
          "routes": [
              {
                  "source": "^/(.*)$",
                  "target": "$1",
                  "authenticationType": "xsuaa",
                  "destination": "srv_api",           
                  "csrfProtection": false
                  
              }
          ]
      }
      ​
    • Create a mta.yaml file;
      ID: school
      _schema-version: "2.1"
      version: 0.0.1
      parameters:
        enable-parallel-deployments: true
      ##############  MODULES  ##################################
      modules:  
      #### We can see that module name DB is created as application, it will be in a stopped state most of the time, it is used only during deployment for HDB modules.
        - name: school-db
          type: hdb
          path: db
          build-parameters:
            ignore: ["node_modules/"]
          parameters:
            memory: 256M
            disk-quota: 256M
          requires:
            - name: school-db-hdi-container
      #### The SRV Module is the backend of application, It will be started      
        - name: school-srv
          type: nodejs
          path: srv
          build-parameters:
            ignore: ["node_modules/"]    
          parameters:
            memory: 256M
            disk-quota: 256M
          provides:
            - name: srv_api
              properties:
                url: ${default-url}
          requires:
            - name: school-db-hdi-container
            - name: school-xsuaa
      #### App Router used to authentication          
        - name: school-app-router
          type: nodejs
          path: app
          build-parameters:
            ignore: ["node_modules/"]    
          parameters:
             disk-quota: 256M
             memory: 256M
          requires:
            - name: school-xsuaa
            - name: srv_api
              group: destinations
              properties:
                forwardAuthToken: true
                strictSSL: false
                name: srv_api
                url: ~{url}
      ##############  RESOURCES  ##################################      
      resources:
        - name: school-db-hdi-container
          parameters:
            service: hanatrial
            service-plan: hdi-shared  
          type: com.sap.xs.hdi-container
          properties:
            hdi-container-name: ${service-name}
      ### XSUAA service instance      
        - name: school-xsuaa
          parameters:
            path: ./xs-security.json  
            service: xsuaa    
            service-plan: application
            service-keys: 
              - name: school-xsuaa-key      
          type: com.sap.xs.uaa    
      ############################################################      
      ​
  5. Now you can build the application mtar file. To Build the mta file execute this command:
    cds build/all --clean && mbt build -p=cf"​
  6. And finally, deploy the app on Cloud Foundry.
    cf deploy mta_archives/school_0.0.1.mtar​

The NPM Modules used in the authentication process

@sap/xssec: XS Advanced Container Security API for node.js

This module is responsible for authentication for node applications in XS Advanced relies on a special usage of the OAuth 2.0 protocol, which is based on central authentication at the UAA server that then vouches for the authenticated user’s identity via a so-called OAuth Access Token. The current implementation uses as access token a JSON web token (JWT), which is a signed text-based token following the JSON syntax.

@sap/xsenv

Utility for easily reading application configurations for bound services and certificates in the SAP Cloud Platform Cloud Foundry environment, SAP XS advanced model and Kubernetes (K8S).

References

MTA Model: https://www.sap.com/documents/2016/06/e2f618e4-757c-0010-82c7-eda71af511fa.html

Cloud MTA Build Tool: https://sap.github.io/cloud-mta-build-tool/

Authentication in CAP Projects https://cap.cloud.sap/docs/node.js/authentication

Assigned Tags

      7 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Cícero Bernardino
      Cícero Bernardino

      Very good!!

      Author's profile photo Marius Obert
      Marius Obert

      Nice post Balbino!

      Btw: You can define the “cds build” in the mta.yaml descriptor. This way, you can only call “mbt build”  ?

      build-parameters:
        before-all:
          - builder: custom
            commands:
              - yarn install
              - cds build/all
      Author's profile photo Balbino Soares Ferreira Filho
      Balbino Soares Ferreira Filho
      Blog Post Author

      Thanks, Marius! Excellent tip!

      Author's profile photo Enric Castella Gonzalez
      Enric Castella Gonzalez

      Nice post!

       

      Thanks for this explanation!

       

      Regards

      Enric

      Author's profile photo Pieter Janssens
      Pieter Janssens

      Given this exact sample srv/uaa requirement: Is it possible to achieve the same result via 'cf push' to the deploy srv + approuter, without using an mta?

       

      Author's profile photo Anjaly Madhu
      Anjaly Madhu

      Clearly explained.

      Thank you so much

      Author's profile photo Sriharsha C R
      Sriharsha C R

      We have a use case, to integrate the User Management services. We have been able to create the instance of XSUAA, with "apiaccess" service plan (defined in MTA). After binding this to the "app-srv", The app-srv crashes while deployed, it would help if it's possible to shine some light on this.

      Best Regards,

      Harsha

       

      Source: Is it possible to configuring multiple XSUAA service plans application and apiaccess in MTA? | SAP Community