Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 

Overview


This blog post is part of the SAP Business Technology Platform Showcase series of blogs and videos. We invite you to check this overall blog, so you can understand the full end-to-end story and the context involving multiple SAP BTP solutions.

Here we will expand the Blog 5: Develop a SAP HANA Cloud native application to add authentication to the data from SAP HANA we exposed as an OData service and then connect it to an AppGyver application.

SAP recently announced that it had acquired AppGyver, a no-code app development platform. With this acquisition, SAP is better able to help customers and partners adapt their IT systems efficiently to their specific needs and optimize the usability of their applications. When combined with the enterprise capabilities that SAP BTP has to offer, SAP is unleashing some interesting possibilities, such as consuming SAP HANA Cloud data on an easy and fast way to build an application.

We will leverage the Authentication & Trust Management service (xsuaa)  from the SAP BTP to manage user authorizations.  User authorizations are managed using technical roles at the application level, which can be aggregated into business-level groups and role collections for large-scale cloud scenarios. When used combined with Cloud Application Programming Model, we can define the permissions for each role and allow or deny access to a specific service being provided by the application using CDS annotations. We will use also JSON Web Tokens, an industry standard, to authenticate against the application. This means that besides speeding up the security development, our application will have the possibility of connecting to non-SAP systems too.

Below you can see that this blog is part of the 5th step of the “Solution Map” prepared for the journey on the referred overall blog:


SAP BTP Showcase – Overall Technical Architecture


You can find the repository with the example code here that will be developed on this post here.

Prerequisites



Scenarios


Using Mocked Authentication


First, we will mock the authentication. This resource provided by SAP Cloud Application Programming Model allows us to quickly test our application with different users and roles. This authentication uses passport and basic authentication to mock the users. Please note that this strategy is only a way to accelerate the development, it is not supposed to be used in production. The strategy that will be used after we deploy will the Token-Based Authentication, which will be shown later on this blog.

Install the passport dependency using the command below:
npm install passport

Then, on the package.json file of our project, add the following auth property under the cds property:
"auth": {
"passport": {
"strategy": "mock",
"users": {
"<YOUR_MOCKED_USER>": {
"password": "<YOUR_MOCKED_PWD>",
"roles": [
"<YOUR_MOCKED_ROLE>"
]
}
}
}
}

You should have something like this on the cds section:
"cds": {
"requires": {
"db": {
"kind": "hana"
}
},
"hana": {
"deploy-format": "hdbtable"
},
"auth": {
"passport": {
"strategy": "mock",
"users": {
"<YOUR_MOCKED_USER>": {
"password": "<YOUR_MOCKED_PASSWORD>",
"roles": [
"<YOUR_MOCKED_ROLE>"
]
}
}
}
}
}

Under the "users" property from the passport strategy you can define the users and the roles that you want to mock. In this case, we will only be mocking one user with one role. However, you can add multiple users and multiple roles.

Now, we must define which endpoints will be secured with authentication. To do this, open the energy-production-plan-values.cds file under the srv folder from our project, where the services are being exposed. We will add a simple cds annotation to demonstrate how to block unauthenticated and unauthorized users from accessing a determined service. For detailed possibilities and capabilities for the usage of access control, please check out the official documentation. Add the @requires annotation to the service, as shown below:
service ProductionPlanValuesService @(requires: '<YOUR_MOCKED_ROLE>'){
entity Values as projection on db.ENERGY_PRODUCTION_PLAN_VALUES;
}

This annotation will request for the mocked user to have the mocked "test-role" that was defined on the package.json file.

And that´s it! We can go ahead and test our application by issuing the command below:
cds watch

Once you access the secured endpoint from the application, you should see an alert requiring for you to sign in as shown below:


If you enter the user and password that you defined on the package.json file earlier, you should be able to see the records from SAP HANA Cloud being provided by the service.

That´s great! You are now able to quickly test different authentication and authorization scenarios for your application. However, we still have to configure the application to use the token-based authentication, which is the strategy used in production.

Using Token-Based Authentication (JWT)


The user identity, roles, and attributes are provided at runtime by a bound instance of the SAP Authorization and Trust Management. This is done through a JWT token in the Authorization header of incoming requests for our application. We can configure the roles that will be used in our application and then assign them to the users inside SAP BTP in the form of role collections.

To activate this strategy, we first need to install the @Sap/xssec and @Sap/xsenv packages:
npm install @sap/xssec @sap/xsenv

Now, we will create and bind the Authorization and Trust Management service to our application. Create a xs-security.json file on the root folder of our project using the command below:
cds compile srv/ --to xsuaa > ./xs-security.json

This will automatically compile all the authentication and authorization annotations that you included on the srv folder and will be used to create the application roles once we deploy the authentication service. Your xs-security.json should look something like this:
{
"xsappname": "csm-demo-202002-plan-srv",
"tenant-mode": "dedicated",
"scopes": [
{
"name": "$XSAPPNAME.viewer",
"description": "viewer"
}
],
"attributes": [],
"role-templates": [
{
"name": "viewer",
"description": "generated",
"scope-references": [
"$XSAPPNAME.viewer"
],
"attribute-references": []
}
]
}

Then, we are going to create the xsuaa (Authorization and Trust Management) service through the command line. To do this, you must connected to Cloud Foundry. Run the command below:
cf create-service xsuaa application <YOUR_APP_NAME>-uaa -c ./xs-security.json

After running this command, you are capable of updating the xsuaa service accordingly to the changes you made to the project by running the cds compile command again and then the command below:
cf update-service xsuaa application <YOUR_APP_NAME>-uaa -c ./xs-security.json

Now, we are going to create a service key for the xsuaa service. This key will be added to the default-env.json file from the application so that the project knows which service it needs to use when running locally for testing. Run the command below:
cf create-service-key <YOUR_APP_NAME>-uaa <YOUR_APP_NAME>-uaa-key

Then run the command below to retrieve the contents from the service key:
cf service-key <YOUR_APP_NAME>-uaa <YOUR_APP_NAME>-uaa-key

Now, add the the key you just retrieved to the VCAP_SERVICES.xsuaa.credentials property. Your default-env.json file should look something like below:
{
"VCAP_SERVICES": {
"xsuaa": [

{
"name": "<YOUR_APP_NAME>-uaa",
"label": "xsuaa",
"tags": [
"xsuaa"
],
"credentials":{
"<YOUR_UAA_KEY_CREDENTIALS>"
}
}
],
"hana": [
{
"name": "<YOUR_DB_INSTANCE_NAME>",
"tags": [
"hana"
],
"credentials": {
"<YOUR_DB_KEY_CREDENTIALS>"
}
}
]
}
}

Also, in the package.json file, add a uaa section in the cds.requires properties, change the passport strategy to JWT, and run the command below to install the node modules that are required at runtime to authenticate the user and to read the JSON Web Token:
npm install --save passport @sap/xssec @sap/audit-logging

By now, your cds properties should be similar to this:
"cds": {
"requires": {
"db": {
"kind": "hana"
},
"uaa": {
"kind": "xsuaa"
}
},
"hana": {
"deploy-format": "hdbtable"
},
"auth": {
"passport": {
"strategy": "JWT",
"users": {
"<YOUR_MOCKED_USER>": {
"password": "YOUR_MOCKED_PWD",
"roles": [
"YOUR_MOCKED_PWD"
]
}
}
}
}
}

Now, we can do some local testing to see everything is correct. Run the command below to visualize the strategy configuration that is being used in the project:
cds env list auth.passport

You should have this response output:
auth.passport.kind = mocked-auth
auth.passport.strategy = JWT
auth.passport.users.* = true
auth.passport.users.alice.roles = [ 'admin' ]
auth.passport.users.bob.roles = [ 'builder' ]
auth.passport.users.<YOUR_MOCKED_USER>.password = <YOUR_USER_PWD>
auth.passport.users.<YOUR_MOCKED_USER>.roles = [ '<YOUR_USER_ROLE>' ]

Don´t worry about the mocked, they will be ignored as the strategy is set to JWT. Then run the application with the command below:
cds watch

When you access the secured endpoint, you should see the error message below. This means that now we need to provide a valid JWT on the request header to access the resource and everything was configured correctly:


Before we can deploy the application to SAP BTP, we need to define on the MTA.yaml file that the srv module of our project will require the uaa service that we created earlier. On the requires section from the MTA file, add the uaa resource as shown below. Please be very aware about the indentation.
- name: <YOUR_APP_NAME>-uaa
# ------------------------------------------------------------
type: org.cloudfoundry.managed-service
parameters:
path: ./xs-security.json
service: xsuaa # or 'hanatrial' on trial landscapes
service-plan: application
properties:
hdi-service-name: ${service-name}

Also, require the resource we just added to the srv module. Your srv module should be as shown below:
- name: <YOUR_APP_NAME>-srv
type: nodejs
path: gen/srv
requires:
- name: <YOUR_APP_NAME>-uaa
- name: <YOUR_APP_NAME>-db
provides:
- name: srv-api
properties:
srv-url: "${default-url}"

Great! Now we can build the MTA file by right clicking on it:


This will generate an MTAR file under the mta_archives folder, which will be used to do the deploy to SAP BTP. Right click on the file and click on deploy.


Once the deploy has been completed, if we access the secured route for the application, we should get the same error message we saw before. There are two reasons this is happening now: we did not include the JWT on the request header and our user is not assigned with the application role yet. Before we add the JWT to request header, we will add an application role collection to our user on the SAP BTP. Access the application roles as shown below. You should be able to visualize all the roles that were created using the xs-security.json file from our project.


Now, head over to the subaccount level and access the role collections. Click on the Create New Role Collection button and enter <YOUR_APP_NAME>-role-collection as the name.


Select the role collection that you created to add users and roles for it. Click on the edit button. Add the application role you created for the project and an user registered in the identity provider selected. Then, click on the save button.


Great, now we can finally go ahead to retrieve a valid JWT from xsuaa service and use it to authenticate and access the resource we created. Go to the development space where you created the xsuaa service. Open its credentials and write down the URL, the clientSecret and the clientId, as we will need them later on.


Now we have everything to proceed to Postman and do some testing to see if everything is working as expected. We will use the URL from the xsuaa service to retrieve the JWT for the user. On Postman, select post as the request type and enter the URL followed by /oauth/token. Then, configure the request body to use x-www-form-urlencoded as the conten-type and set the request body with the values as shown below:


For more information about the token endpoint, please access the official Cloud Foundry documentation.

For the Authorization header of the request, select basic authentication and inform the clientId and the clientSecret from xsuaa as the username and password respectively, as shown below:


After doing that, go ahead and click on the send button. If everything is correct, you should be able to see the JWT provided for the user on the response body. Copy the access token, this is the token that will be used on the request header for our OData service.


Create another request on Postman. Select get for this request and enter the secured OData endpoint that we created for the project. Set the Authorization header to be bearer token and paste the token that we generated on the last step. If everything was configured correctly, we should be able to retrieve the records from SAP HANA Cloud.



Conclusion


Congratulations! You are now capable of implementing an authorization flow using SAP Cloud Application Programming Model and the xsuaa service to integrate both SAP and non-SAP technology.

For the second part of this blog, I will demonstrate how to authenticate an user in AppGyver using the authentication flow we just created.