Skip to Content
Technical Articles
Author's profile photo Denys van Kempen

Authorization using XSUAA | Migrating from the Neo Environment to the Multi-Cloud Foundation

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!

/wp-content/uploads/2016/02/sapnwabline_885687.png

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.

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

/wp-content/uploads/2016/02/sapnwabline_885687.png

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.

/wp-content/uploads/2016/02/sapnwabline_885687.png

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.

/wp-content/uploads/2016/02/sapnwabline_885687.png

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

/wp-content/uploads/2016/02/sapnwabline_885687.png

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');
  }
});

/wp-content/uploads/2016/02/sapnwabline_885687.png

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

/wp-content/uploads/2016/02/sapnwabline_885687.png

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.

/wp-content/uploads/2016/02/sapnwabline_885687.png

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).

/wp-content/uploads/2016/02/sapnwabline_885687.png

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.

/wp-content/uploads/2016/02/sapnwabline_885687.png

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.

/wp-content/uploads/2016/02/sapnwabline_885687.png

Business Logic App | Java

Spring Boot

For an example using Java, see

/wp-content/uploads/2016/02/sapnwabline_885687.png

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

/wp-content/uploads/2016/02/sapnwabline_885687.png

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.

/wp-content/uploads/2016/02/sapnwabline_885687.png

Assigned Tags

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

      Hi Denys van Kempen

      Most of the code is not in updated in your github repository (for example )

      xs-security.json
      Author's profile photo Denys van Kempen
      Denys van Kempen
      Blog Post Author

      A little exaggeration perhaps? Most? Any other examples?

      The security descriptor file is in the repo.

      Any idea why you could not find it?

      Convention calls for storing this file either under the root of the project (with manifest.yml) or otherwise in a separate security directory.