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

Deploying a CAP based Fiori app to a central Launchpad – Part2: Add Authentication

Introduction

Recently I posted the following blog.
Deploying a CAP based Fiori app to a central Launchpad
If you follow the steps described there, you can get rid of Approuter, because the central Launchpad does the work of Approuter. After publishing the blog, I received a question asking, “How can we implement authentication and authorization checks for CAP without Approuter?” The answer is, the Launchpad takes care of them too! So why not give it a try?

In this blog, I’m going to add authentication and authorization checks to the app which I have build in my previous blog. The content is available at GitHub.

Steps

  1. Clone the repository from GitHub
  2. Add authorizations to CAP service
  3. Configure xs-app.json
  4. Install dependencies
  5. Configure package.json
  6. Configure xs-security.json (optional)
  7. Configure mta.yaml
  8. Build & Deploy

 

1. Clone the repository from GitHub

1.1. Clone the repository.

//If you deploy to HANA Cloud
git clone https://github.com/miyasuta/central-launchpad-cap.git
//If you deploy to HANA Service (Trial)
git clone -b hana-service https://github.com/miyasuta/central-launchpad-cap.git

 

1.2. Run the CAP service locally.

npm install
cds watch

 

2. Add authorizations to CAP service

The scenario is to allow users to view books data created by themselves only.

2.1. Add createdBy field to Books entity in db/data-mode.cds.

namespace my.bookshop;

entity Books {
  key ID : Integer;
  title  : String;
  stock  : Integer;
  createdBy: String  @cds.on.insert : $user; //add
}

2.2. Add the same field to db/data/my.bookshop-Books.csv.

ID;title;stock;createdBy
1;Wuthering Heights;100;<your scp userID>
2;Jane Eyre;500;<NOT your scp userID>

2.3. Add the following annotations to srv/cat-service.cds.

using my.bookshop as my from '../db/data-model';

service CatalogService @(requires: 'authenticated-user') {
    entity Books as projection on my.Books;
}

annotate CatalogService.Books with @(restrict: [
    { grant: ['READ'], where: 'createdBy = $user'}
]);

At this point, an error occurs at the terminal. I’ll fix this next.

2.4. Install passport.

By installing passport, above error will disappear.

npm install passport

 

3.Configure xs-app.json

Go to app/fiori/xs-app.json and remove “authenticationType: none” from the CAP service route. By doing so default authentication type “xsuaa” will be applied to this route.

{
  "welcomeFile": "/index.html",
  "authenticationMethod": "route",
  "logout": {
    "logoutEndpoint": "/do/logout"
  },
  "routes": [
    {
      //"authenticationType": "none", Remove this
      "csrfProtection": false,
      "source": "^/catalog/",
      "destination": "cap-launchpad"
    },
    {
      "source": "^(.*)$",
      "target": "$1",
      "service": "html5-apps-repo-rt",
      "authenticationType": "xsuaa"
    }
  ]
}

 

4. Install dependencies

Install the following modules for JWT-based authentication.

npm install @sap/xssec @sap/xsenv

 

5. Configure package.json

Add “uaa” section to package.json.

    "cds": {
        "requires": {
            "db": {
                "kind": "sql"
            },
            "uaa": {
                "kind": "xsuaa"
            }
        }
    }

 

6. Configure xs-security.json (optional)

If there’s a requirement to create new roles, configure xs-security.json like below sample.
In this specific project I don’t need additional roles, so I skip this step.

{
  "xsappname": "fiori",
  "tenant-mode": "dedicated",
  "scopes": [
    {
      "name": "$XSAPPNAME.admin",
      "description": "admin"
    },
    {
      "name": "uaa.user",
      "description": "UAA"
    }    
  ],
  "attributes": [],
  "role-templates": [
    {
      "name": "admin",
      "description": "generated",
      "scope-references": [
        "$XSAPPNAME.admin"
      ],
      "attribute-references": []
    },
    {
      "name": "Token_Exchange",
      "description": "UAA",
      "scope-references": [
        "uaa.user"
      ]
    }    
  ]
}

 

7. Configure mta.yaml

Add xsuaa service (“uaa_fiori” in this case) as required resource of CAP service and db-deployer.

 # --------------------- SERVER MODULE ------------------------
 - name: cap-launchpad-srv
 # ------------------------------------------------------------
   type: nodejs
   path: gen/srv
   parameters:
     memory: 256M
     disk-quota: 1024M
   requires:
    # Resources extracted from CAP configuration
    - name: cap-launchpad-db
    - name: uaa_fiori //add
   provides:
    - name: srv-api      # required by consumers of CAP services (e.g. approuter)
      properties:
        srv-url: ${default-url}

 # -------------------- SIDECAR MODULE ------------------------
 - name: cap-launchpad-db-deployer
 # ------------------------------------------------------------
   type: hdb
   path: gen/db  
   parameters:
     buildpack: nodejs_buildpack
   requires:
    # 'hana' and 'xsuaa' resources extracted from CAP configuration
    - name: cap-launchpad-db
    - name: uaa_fiori //add
resources:
...
 - name: uaa_fiori
   type: org.cloudfoundry.managed-service
   parameters:
     path: ./xs-security.json
     service: xsuaa
     service-name: fiori-xsuaa-service
     service-plan: application

 

8. Build & Deploy

8.1. First go to app/fiori folder and install dependency (so that build will not fail).

cd app/fiori
npm install

 

8.2. Go back to the project root and execute build.

mbt build

 

8.3. Deploy mtar file to Cloud Foundry.

cf deploy mta_archives/cap-launchpad_1.0.0.mtar

 

After successful deployment, go to your Launchpad site and execute the app. (I you have not configured your Launchpad yet, please refer to the step 6 of my previous blog).
You will only see the record ID 1, as your user ID is set as createdBy only for this record.

 

Conclusion

The central Launchpad takes care of authentication and authorization tasks.

The steps to enable authentication and authorization is almost the same as CAP & Approuter project. The only difference would be where you define routes for CAP service: In Approuter approach, you would configure routes in xs-app.json in Approuter, whereas in central Launchpad approach, you configure routes in xs-app.json under html5 application module.

 

References

Assigned tags

      6 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Yogananda Muthaiah
      Yogananda Muthaiah

      Looks good !!!

      Author's profile photo Savio Marques
      Savio Marques

      Thanks so much for the post and all information!

       

      Those posts help me soo much with my project.

       

      My apps now are deployed in Lauchpad service successfully.

       

      But I have one question.

       

      I realized in MTA file, the resource org.cloudfoundry.managed-service, has the property ForwardAuthToken, and checking in the SAP HELP documentation, the property described is HTML5.ForwardAuthToken.

       

      which one is correct?

       

      And the another problem, is when I add some records in a Entity with "managed" aspect, the user is still filled as anonymous

       

       

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

      Hi Savio,

      Thanks for your comment. Glad that this blog helped you.

      Regarding destination property, you're right. According to the document, HTML5.ForwardAuthToken is the correct one.

      About anonymous user issue, please refer to Jodel's blog - OData Context on OData Create Operation section.

      It seems that need to use transaction object to set user information to db.

      Regards,

      Mio

      Author's profile photo Savio Marques
      Savio Marques

      Mio, thanks so much for the information! I realized that the anotation "@(requires:  'authenticated-user') was missing in the cds service. I re-deployed the app with those corrections and worked fine!!!

      One more thing. The app ui (html5 module) in MTA doesn't have to be binded with the xsuaa service?  Just the server module, the sidecar module and the application content module?

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

      Hi Savio,

      Thanks for the update. Your input has helped me implement insert operation to my project.

      html5 module doesn’t have to be bound to the xsuaa service, because it is launchpad that takes care of authentication, and html5_repo_host is just a repository for html5 content.

       

       

      Author's profile photo Holger Schäfer
      Holger Schäfer

      Hi Mio,
      thank you for the great second blog (again).

      I additionally was having issues with my authentication using

      annotate ManageService with @(requires : 'authenticated-user');

      i also had to explicitely define JWT strategy

        "cds": {
          "requires": {
            "uaa": {
              "kind": "xsuaa"
            },
            "auth": {
              "[production]": {
                "strategy": "JWT"
              }
            }...

      to get it working with the destinations. I used this only for production, because locally i am using mock strategy with mock users instead.

      This issue was introduced with CAP 4.x (it was formerly working with out this setting for me ?!?).

      Anyhow, great to have my PoCs running in SAP Cloud Launchpad.

      Best Regards
      Holger