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: 
dvankempen
Product and Topic Expert
Product and Topic Expert






This blog post series is about developing applications in a multi-cloud environment.

For the end-to-end hands-on tutorial example, see

For the step-by-step series, visit

  1. Cloud Foundry, UAA, and XSUAA

  2. Business Logic App

  3. Service Instance (SAP HANA Cloud)

  4. Application Router

  5. Authentication using XSUAA

  6. Authorization using XSUAA <<< this post

  7. Multi-target applications (MTA)

  8. Application Runtime (Appendix)


Questions? Post as comment.

Useful? Give us a like and share on social media.

Thanks!



Hands-On Tutorials


Developing Secure Applications on the SAP Cloud Platform


In this blog series, we explore authentication and authorisation using XSUAA in the SAP Cloud Platform, Cloud Foundry environment.

In this blog, we cover how we can perform authorization checks in our business logic. For this we will

  • Define scopes and role templates in the security descriptor file for the XSUAA service | xs-security.json.

  • Add the body-parser package to the approuter to parse JSON from HTTP POST.

  • Add XSUAA Container Security API methods to our Business Logic App to perform authorization checks.

  • Create a role collection adding roles and adding user(s) using SAP Cloud Platform cockpit.


Video Tutorial


In this seventh video of the series, we explore authorizarion using XSUAA service with some code changes to the business logic of our services app and to the front-end, the app router.

https://youtu.be/hfKkclnhVHQ

Sample Code


As before, we continue with the (slightly modified) sample code from SAP Cloud Platform documentation:

You can download the sample code from repository

Appendix


For more detailed information about the SAP Cloud Platform trial environment, Cloud Foundry buildpacks, dependencies declarations, attributes, Diego cells and more, see the "appendix" blog


Application Router


We continue with the approuter as configured in the previous blog where we installed the @sap/approuter package and defined the route(s) in the xs-app.json file.

User Interface | Index.html


So far we have used a very simple home page (index.html) for the web entry point (approuter) of our business logic application.

In this example, we are going to do something a little bit more elaborate: view and update users.

The body of the page contains a link to trigger a GET request: /myapp/users (same as before) and a button and input box for a POST request.

The JavaScript required to support this is defined in the header. We need to fetch a CSRF token first before sending the POST. This is why the addUser function calls addNewUser inside fetchCsrfToken and we need a bit more code then before on our home page.

See learn.jquery.com/ajax for more information about jQuery and AJAX. For the token, see cross-site request forgery.



XSUAA Service Instance


Security Descriptor | xs-security.json


When we created an XSUAA service instance previously we only provided the name of the business logic app with the tenant mode as dedicated.

For the authorisation check, we now add

  • two scopes (Display, Update)

  • two role templates (Viewer, Manager)

  • two role collections (Viewer, Manager)


After we have deployed the app, we will need to assign these role collections to our user. The scopes are references in the business logic app.



Update XSUAA Service Instance


To update the XSUAA service instance we can use either the CLI or the SAP Cloud Platform cockpit.

Command Line


As before, we can pass the JSON either in-line or as file.

As documented

cf service myxsuaa
cf update-service myxsuaa -c security/xs-security.json

SAP Cloud Platform cockpit


Alternatively, go to Service Instances in your Cloud Foundry space, select the instance, select update, and either upload the JSON file or provide it in-line.



Business Logic App | Node.js


Database | Users.json


We have seen that for authorised users, the UI returns a list of users and an option to add users. Most often, you would use some kind of database for this but to keep our example simple we are going to use a file.

To get started, create a file named users.json in the business logic app.



Application Descriptor | Package.json


For our app to make sense of the JSON passed in the body of REST API POST call we need a body parser. Below the code from the addNewUser(token) function in index.html where the name is converted to a JSON string.
jQuery.ajax({
url: '/myapp/users',
type: 'POST',
headers: { 'x-csrf-token': token },
contentType: 'application/json',
data: JSON.stringify({ name: name })
})

Body-parser is already included with express but we can install it to update the package to the latest version and have it listed as dependency in the application descriptor file package.json.
npm i body-parser

As documented



Business Logic | Server.js


Update the business logic of the app to include an app.get and app.post function corresponding to the UI. For both a scope check is performed, as defined in the security descriptor (xs-security.json).

  • non authorized users get a 403

  • app.get returns the content of the users.json file.

  • app.post adds a line to the file.


The Container Security API method and properties (checkScope) as documented



App Deployment


Command Line


To deploy the app run the cf push command. No changes were made to the manifest except for the removal of the hdicontainer-1 service instance as we are not using the SAP HANA Cloud database here in this example.
# housekeeping
cf d[elete] myapp -r -f
# deploying
cf push
# running
cf a[pps]



Unauthorized


As before, accessing the business app directly (myapp) returns HTTP 401 Unauthorized and accessing the approuter /myapp URL forwards the request to the identity provider for authentication.



Authenticate


As before, when we access the approuter URL the request is forwarded to the identity provider.



UI | Approuter Home


After log on, the home page (index.html) of the app router displays where we can view the list of users (file users.json) or add users.



UI | Forbidden


However, without authorisation access is forbidden. In other words, our account has been authentication but is not authorised (yet).


This is the result of the the app.get method which returns Forbidden in case the required scope is not found in the JWT.
app.get('/users', function (req, res) {
var isAuthorized = req.authInfo.checkScope('$XSAPPNAME.Display');
if (isAuthorized) {
res.status(200).json(users);
} else {
res.status(403).send('Forbidden');
}
});


Scopes, Roles, Role Templates and Role Collections


SAP Cloud Platform Cockpit | APPNAME > Security


Above, we configured the XSUAA service with a security descriptor (xs-security.json), which defined two scopes (<appname> Display and Update) and two role templates with role collections (Viewer, Manager).

As we have bound (manifest.yml) both approuter and myapp to myxsuaa, a service instance of XSUAAA, both the roles, scopes, and role templates are listed under App Name > Security.



SAP Cloud Platform Cockpit | Subaccount > Security > Trust Configuration


As we have seen, authentication for the Cloud Foundry environment (the subaccount that is which corresponds to a Cloud Foundry Org) has been delegated to an identity provider of which the default for the SAP Cloud Platform is the SAP ID Service.

To authorise users for our business logic app, we need to add a role collection to the user.



SAP Cloud Platform Cockpit | Subaccount > Security > Trust Configuration > [IdP] > Role Collection Assignment


By default on the trial environment, there is only a single user (your account) with a single role collection granted (subaccount administrator). When we select the IdP (sap.default), Role Collection View Assignment is displayed. Here we can view and assign role collections



SAP Cloud Platform Cockpit | Subaccount > Security > Roles


At the subaccount level, the roles (and role templates) are listed under Roles.



SAP Cloud Platform Cockpit | Subaccount > Security > Role Collection


When the role collection already exists, this can also be done from Subaccount > Security > Trust Configuration > [IdP] > Role Collection Assignment.

The assignment is also displayed under APPNAME > Security > Roles



Business Logic App | Node.js


Viewer


With the Viewer role granted, the Show Users link on the approuter home page now returns a result.


As expected, adding a user still returns 403: Forbiddden.


This alert is triggered by the addNewUser function on the approuter home page.
function addNewUser(token) {
var name = jQuery('#name').val() || '--';
jQuery.ajax({
url: '/myapp/users',
type: 'POST',
headers: { 'x-csrf-token': token },
contentType: 'application/json',
data: JSON.stringify({ name: name })
})
.done(function() {
alert( 'success' );
window.location = '/myapp/users'
})
.fail(function(jqXHR, textStatus, errorThrown) {
alert('Error adding new user: ' + jqXHR.status + ' ' + errorThrown);
});
}

Manager


When we add the Manager role to the myapp role collection to which our user is assigned, we can also perform the POST request.

Alternatively, create a new role collection, add the Manager role, and grant the role collection to the user.





Business Logic App | Python


The sample Python Business Logic app is less sophisticated as we only perform an authorization check in the business logic on the openid scope. As the SAP ID Service uses OAuth 2.0, this is assigned to the user by default.

Business Logic | server.py


For our Python app, we add sap-xssec and perform an authorization check on the security context and openid scope. If not authorized abort, otherwise proceed with a database query.
def db():
if 'authorization' not in request.headers:
abort(403)
access_token = request.headers.get('authorization')[7:]
security_context = xssec.create_security_context(access_token, uaa_service)
isAuthorized = security_context.check_scope('openid')
if not isAuthorized:
abort(403)

As documented

Note that we can call env.get_service by label or name (amongst others).



Application Router


We continue with the approuter as configured in the previous blog where we installed the @sap/approuter package and defined the route(s) in the xs-app.json file,

User Interface | Index.html


The 'home" page of the approuter simply displays two links:

  • app.route('/') - returns

  • app.route('/db') with authorization check.




App Deployment


Manifest


As before, no changes were made to the manifest. App binds to the service instances for SAP HANA Cloud and XSUAA.

Command Line


To deploy the app run the cf push command.
# housekeeping
cf d[elete] myapp -r -f
# deploying
cf push
# running
cf a[pps]

403 Forbidden


We did not require authorization or authorization for the home page [ app.route('/') ]. However, when we attempt to access myapp/hana [ app.route('/db') ] HTTP 430 Forbidden is returned.


When we access the approuter, we first need to authenticate (as before).



UI | Authenticated


After authentication, the approuter home page is displayed.



UI | Authorized


To access the database, only the openid scope is required.



Business Logic App | Java


Spring Boot


For an example using Java, see



Please Proceed


We are done with the tutorial series but should you want to know more about buildpacks, runtimes, vendor dependencies, application routes, and other application attributes which were slightly off-topic  for our main story, visit


Share and Connect


Questions? Please post as comment.

Useful? Give us a like and share on social media.

Thanks!

If you would like to receive updates, connect with me on

For the author page of SAP PRESS, visit








Over the years, for the SAP HANA Academy, SAP’s Partner Innovation Lab, and à titre personnel, I have written a little over 300 posts here for the SAP Community. Some articles only reached a few readers. Others attracted quite a few more.

For your reading pleasure and convenience, here is a curated list of posts which somehow managed to pass the 10k-view mile stone and, as sign of current interest, still tickle the counters each month.


2 Comments