Add authentication - SAP CAP Guide 3

Adding authentication to a service is not very complicated at all and that is one of the major improvements with the SAP Cloud Application Programming Model. A few years back they was no way to simple add authentication to a simple application within 5 minutes, but with the CAP we have that option. We will be restricting our recently created service to be only accessible to authenticated users, so users that are logged in.

Restrict service

To restrict a service you just need to add an annotation to the service, which you can do using the @-symbol. To restrict a service just add @requires: 'authenticated-user' and the service cannot be accessed by unauthorized users. You cannot only use authenticated-user, but every group name that you like, while authenticated-user is automatically granted to all users which are logged in. We will cover on how to use group and further restrictions later on. After adding our annotation our service might look like this:

service ExploreService @(path:'/explore') {
    @requires: 'authenticated-user'
    entity Books as select from my.Books {
       key ID, title, author, stock
    };

    entity Authors as select from my.Authors {
        key ID, name, books
    };

    entity Orders as projection on my.Orders ;
}

After saving, you can already check if the authentication works. Just try to load the service again http://localhost:4004/explore/ and you will notice, that a login prompt appears. We have two ways of authentication on our disposal: Mocked authentication and JWT based authentication, but we will only stick to JWT based authentication as mocked authentication should only be used in development and testing and JWT based authentication works for everything after set up correctly.

Create XSUAA service

Now we can create the service which will handle most of our authentication and authorization data. This service will be connected with our platform identity provider. I connected a SAP IAS to my SAP account for that, but you can use the sub account provider as well. Creating this service is quite easy, as we are provided a few tools which make our life a lot easier. The service will be created out of a file, which we can generate with one simple command:

cds compile srv/ --to xsuaa > xs-security.json

Now we can create the service using this file:

cf create-service xsuaa application myproject-uaa -c xs-security.json

After that we can install the necessary packages in our root directory:

npm install --save passport @sap/xssec @sap/xsenv @sap/audit-logging

Now we need to create a new file in our root directory called default-env.json. This file will hold the credentials for our local testing with the XSUAA service:

 {
     "VCAP_SERVICES": {
         "xsuaa": [
             {
                 "name": "xsuaa", "label": "xsuaa", "tags": [ "xsuaa" ],
                 "credentials": {
                 }
             }
         ]
     }
 }

Now as you might noticed the credentials section is empty, so we need to gather the credentials from the service. For that we need to create a service key and read it:

cf create-service-key myproject-uaa myproject-uaa-key 
cf service-key myproject-uaa myproject-uaa-key

Now copy the output into the credentials section in the default-env.json like so:

{
    "VCAP_SERVICES": {
        "xsuaa": [
            {
                "name": "xsuaa", "label": "xsuaa", "tags": [ "xsuaa" ],
                "credentials": {
                    "apiurl": "https://api.authentication.eu10.hana.ondemand.com",
                    "clientid": "sb-myproject!t12345",
                    "clientsecret": "1234567890abcfdef",
                    "identityzone": "s0000000000trial",
                    "identityzoneid": "1234567890",
                    "sburl": "https://internal-xsuaa.authentication.eu10.hana.ondemand.com",
                    "tenantid": "1234567890",
                    "tenantmode": "dedicated",
                    "uaadomain": "authentication.eu10.hana.ondemand.com",
                    "url": "https://s0000000000trial.authentication.eu10.hana.ondemand.com",
                    "verificationkey": "-----BEGIN PUBLIC KEY-----...-----END PUBLIC KEY-----",
                    "xsappname": "myproject!t12345"
                }
            }
        ]
    }
}

Now we need to tell our application that it should use an XSUAA service, otherwise it would simply ignore it. For that go into the package.json and add a new section after „scripts“ looking like:

...
"scripts": {
    "start": "npx cds run"
  },
  "cds": {
    "requires": {
        "uaa": {
            "kind": "xsuaa"
        }
    }
    }
}

Setting up the approuter

The approuter is a component which will be deployed as an individual application. That means our „application“ will consists of 3 applications in Cloud Foundry. The approuter serves as a guard for the services which are behind it, handles routing and manages the authentication. Without authentication you can access the other services like the service we created, but this will just return unauthorized. So to authorize your request, you have to connect using the approuter, which will pass the authentication token to the underlying service. To setup an approuter create a package.json file in the /app directory:

{
   "name": "approuter",
   "dependencies": {
     "@sap/approuter": "^6"
   },
   "scripts": {
     "start": "node node_modules/@sap/approuter/approuter.js"
   }
}

Furthermore we need a file which will handle our routes which will be called default-env.json. There we define the URL of our service later on when we will deploy the application.

{
 "destinations" : [
     {
         "name": "srv_api",
         "url": "http://localhost:4004",
         "forwardAuthToken": true
     }
 ],
"VCAP_SERVICES": {
        "xsuaa": [
            {
                "name": "xsuaa", "label": "xsuaa", "tags": [ "xsuaa" ],
                "credentials": {
				}
            }
        ]
    }
}

Replace the credentials section like as seen in the default-env.json in the root directory. Now navigate in the /app directory with your terminal and install the npm packages and start the approuter:

npm install
npm start

Now try to connect to the approuter instance on localhost:5000

comments powered by Disqus