Skip to Content
Technical Articles
Author's profile photo Vurukuti Govinda Raju Yadav

Cloud Foundry – Using single XSUAA Service (For all Applications including Mobile App)

Introduction : The User Account and Authentication service (UAA) is the central infrastructure component of the Cloud Foundry environment at SAP Cloud Platform for user authentication and authorization. This blog talks about the steps involved in configuring the Mobile services XSUAA Service against the other applications in the CF cockpit.

 

This post is helpful for someone who has the Applications in the CF Cockpit and also has a Mobile application defined/created using the Mobile Services. When you create a Mobile application Mobile services by default create XSUAA Service instance automatically. Now, if you are at a scenario where you have already created custom XSUAA Service instance and bound all the applications to it, you will have two XSUAA Service instances. If your Mobile application uses Server application API’s/ Destinations, accessing those API’s would need an extra authentication. This is because even after the user logs into the Mobile application which means he got authenticated against Mobile services XSUAA, he would need to authenticate again against the server’s custom XSUAA service instance to access the APIs / Destinations. This post assumes you have few Server applications typically Java applications in the CF Cockpit, a custom XSUAA Service instance bound to those applications and also a Mobile application configured in the Mobile services. However, as a quick check I will go through these sections

 

  1. Secure your application in Cloud Foundry
  2. Create a Mobile application in the Mobile Services
  3. Configuration to make Applications use Mobile services XSUAA
  4. Problems and Solutions having a single XSUAA

 

1. Secure your application in Cloud Foundry

I would suggest to go and read https://blogs.sap.com/2017/07/18/step-7-with-sap-s4hana-cloud-sdk-secure-your-application-on-sap-cloud-platform-cloudfoundry/ blog. However, if you are short of time you can go through the below steps

Create XSUAA Service Instance : Before creating the XSUAA Service instance prepare the xs-app.json file. This JSON file contains

  • xsappname
  • tenant-mode
  • scopes
  • role-templates
  • role-collections.
{
  "xsappname": "myapp-server",
  "tenant-mode": "dedicated",
  "scopes": [
    {
      "name": "$XSAPPNAME.appuser",
      "description": "Create HelloWorld"
    }
  ],
  "role-templates": [
    {
      "name": "appuser",
      "description": "Required to perform create, read, update and delete api calls",
      "scope-references": [
        "$XSAPPNAME.appuser"
      ]
    }
  ],
  "role-collections": [{
		"name": "appuser",
		"description": "This is a role collection discription.",
		"role-template-references": ["$XSAPPNAME.appuser"]
	}]
}

Perform the following command from the CLI

xs create-service xsuaa default authorizationtest-uaa -c xs-security.json

Assign the role-collection to the required IDP Users

Go to the Cloud Foundry cockpit’s sub account view. Under Security open Trust configuration. This would open the configured IDP’s. Click on the Active IDP and search for the application user by typing in the email address and clicking on the ‘show assignments’

Click on Add User and then click on ‘Assign Role Collection’

Search and assign the ‘appuser’ role collection.

 

Configure The Application 

Create a Simple Java web application with a Servlet, let’s say here ‘HelloWorld’

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>com.sap.myapp</display-name>
  <login-config>
    <auth-method>XSUAA</auth-method>
  </login-config>
.................

<security-constraint>
    <web-resource-collection>
      <web-resource-name>Web Service</web-resource-name>
      <url-pattern>/helloWorld/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>appuser</role-name>
    </auth-constraint>
  </security-constraint>

..................
</web-app>

Deploy this application and in the cf cockpit go to the application > service bindings.

Click on the ‘Bind Service’ and assign the created XSUAA Service instance to it. After this, accessing the helloWorld API will be only allowed to the users with role-collection ‘appuser’ assigned.

 

As mentioned before there is a much deeper and detailed blog on this one; Please go through this one here

 

2. Create a Mobile application in the Mobile Services

For this please try to go through this https://help.sap.com/viewer/468990a67780424a9e66eb096d4345bb/Cloud/en-US. However, if you are short of time and want to create a Mobile application quickly then you can follow this section.

Creating a Mobile application

Steps to configure Mobile services

  1. Go to the Subaccount level
  2. Go to the Entitlements
  3. Click on the ‘Configure Entitlements’ and All mobile related service plans
  4. Now, go to the ‘Service Marketplace’ in the Space.
  5. Click on any Mobile service and in the overview section click on the Support. This would open a Mobile services cockpit. (Note : Please select the right ‘Organisation’ and ‘Space’ from the drop-downs in the initial page of Mobile services cockpit)

Creating the Mobile application in the Mobile services cockpit

  1. Go to the ‘Native/Hybrid’ sub section under ‘Mobile applications’
  2. Click on the ‘New’
  3. Fill in the application details and click ‘Save’, This would create the application
    1. ID : com.sap.myapp
    2. Name : My App
    3. Client Connection Timeout (ms) : 120000
    4. Backend Connection Timeout (ms) : 30000
    5. Session Timeout (min) : 15

Assigning Features to the Mobile app

  1. In the Mobile services cockpit , Go to the application
  2. Click on the ‘+’ against the Assigned features
  3. A popup opens and please select all the below features and click ‘Ok’
    1. Mobile Client Log Upload
    2. Mobile Client Resources
    3. Mobile Offline Access
    4. Mobile Connectivity
    5. Mobile Push Notification
    6. Mobile Settings Exchange

Configuring the Mobile Connectivity

  1. Go to the ‘Mobile connectivity’ from the list of the ‘Assigned features’
  2. Click on Create new destination icon to create the new destination
  3. This way create all the below destinations
    Com.sap.myapp https://myapp-mark-1.cfapps.eu10.hana.ondemand.com/HellowWorld/
  4. Select the following options while creating the destination
    1. Maximum Connections : 32
    2. Maximum Request Size (bytes) : 1000000
    3. Timeout (ms) : 60000
    4. Online Request Threshold : -1
    5. Rewrite Mode : Rewrite URL
    6. SSO Mechanism : Forward Authentication

 

3. Configuration to make Applications use Mobile services XSUAA

Please go to the Mobile services and check the space under Info > Application Details, you would be able to see XSUAA Client ID. This tells us one thing that for the application that we have created Mobile Services created an XSUAA Service instance.

Now our goal is to use the same XSUAA Service Instance for the other Java applications at the cockpit level.

For this, please go to the Application in the Cloud Foundry cockpit. Go to the Service Bindings. Here, remove the existing binding of custom XSUAA Service instance and assign the Mobile Services XSUAA Service instance.

After doing this, restart the application and try to access it.

After the login, accessing the application url ‘/helloworld’ gives us the 403 forbidden error.

This is because for the XSUAA service instance that was created by the Mobile services doesn’t have the required scopes/roles. For this go to the Mobile services again and under the Security tab against the Role collections click on the Pencil/Edit icon and upload the below json file.

 

{
  "scopes": [
    {
      "name": "$XSAPPNAME.appuser",
      "description": "Create HelloWorld"
    }
  ],
  "role-templates": [
    {
      "name": "DEVTESTER",
      "description": "Required to perform create, read, update and delete api calls",
      "scope-references": [
        "$XSAPPNAME.appuser"
      ]
    }
  ],
  "role-collections": [{
		"name": "appuser",
		"description": "This is a role collection discription.",
		"role-template-references": ["$XSAPPNAME.appuser"]
	}]
}

Notice the above JSON file, we don’t need to specify all the other tags like xsappname, scope and etc. We only need to mention the scopes, role-templates and role-collections that are specific to our application. Alright, go ahead and save this and restart the application as necessary.

Now, Try and hit the /helloworld url after the login it would still show the 403 forbidden which means we are not yet done. One thing if you remember what we have done is to assign the role-collection against the required IDP user. Here, since we have a new role-collection of the new XSUAA Service instance, we would have to repeat the same step. Please go through the section 1 for doing the same.

Finally, try to hit the URL of /helloWorld, after the successful login you should be able to see the response.

Congratulations. You have made changes to use the single XSUAA service instance across your Java applications and Mobile application. What next?. What are the problems you might encounter using the single XSUAA?. I have tried addressing them in the subsequent section.

 

4. Problems and Solutions having one single XSUAA

Let us consider a case where you want to grant an external access to the Applications deployed in the CF. How do you do that?. One way is ‘OAuth Client Credentials’ flow.

In this external application has to get an access token by making an OAuth Client Credentials call. And after that, use the same access token further to make any API calls.

Unfortunately, using this token would still throw 403 forbidden. Why? because if you parse the JWT Access token you would observe the scopes are missing which are required to access the API calls like ‘appuser’. For that, we have to make changes so that the Access token that is generated via the Client Credentials flow, would include the required scopes.

How do we do this then?. Answer is we have to just include the below line as part of the xs-security.json file.

"authorities":["$XSAPPNAME.appuser"]

As pointed above, you would have to go to the Mobile services then to Security tab and then upload a json file having the above mentioned authorities tag. Save it and restart applications as necessary.

Try to get the access token using client credentials flow and use the token to make API call again. Hmmm, No luck even now. This is because when you upload a security.json file in the Mobile services, it only do a merge with the existing security configuration. As part of the merge, it only considers the new scopes, role-templates and role-collections. That means, the last upload we have done is of no use as it ignored the authorities tag.

Ok, Having said that, what option do we have. One thing we can do is to update the Mobile’s XSUAA service from the CLI with the new xs-security.json. But there is a catch here, we would loose all the scopes, roles and other configuration that Mobile services created as update service from CLI is an override operation but not a Merge operation.

How do we solve this then?  Below is the default security.json file. It is for your reference; Now if you have any additional configuration that needs to get into this, Simply put them in and update the service with the new json file from the CLI. This way, your new configuration changes are reflected and the default scopes, roles and etc. that Mobile services had created would still remain.

 

{
	"xsappname": "com-sap-myapp-ldh7tgj2",
	"tenant-mode": "shared",
	"scopes": [{
		"name": "$XSAPPNAME.admin_read",
		"description": "Get configuration from business user"
	}, {
		"name": "$XSAPPNAME.admin_write",
		"description": "Change (CUD) configuration from business user"
	}, {
		"name": "$XSAPPNAME.pushregistrations_read",
		"description": "Get push registrations"
	}, {
		"name": "$XSAPPNAME.push_single",
		"description": "Push to single"
	}, {
		"name": "$XSAPPNAME.push_multiple",
		"description": "Push to multiple"
	}, {
		"name": "$XSAPPNAME.push_all",
		"description": "Push to all"
	}, {
		"name": "$XSAPPNAME.clientlog_read",
		"description": "Read uploaded Client Logs"
	}, {
		"name": "$XSAPPNAME.access_staged_app",
		"description": "Receiving a staged revision of an application from Mobile App Update service."
	}, {
		"name": "$XSAPPNAME.Callback",
		"description": "With this scope set, the callbacks for tenant onboarding, offboarding and getDependencies can be called.",
		"grant-as-authority-to-apps": ["$XSAPPNAME(application,sap-provisioning,tenant-onboarding)"]
	}, {
		"name": "$XSAPPNAME.appuser",
		"description": "Default scope."
	}],
	"authorities": ["$XSAPPNAME.appuser"],
	"role-templates": [{
		"name": "uaaUser",
		"description": "An indicator for UAA users in order their access tokens can be exchanged to access depending services. It needs not be explicitly mapped to any Role Collection.",
		"scope-references": ["uaa.user"]
	}, {
		"name": "userAttributes",
		"description": "An indicator for users to retrieve SAML Attributes from user_info endpoint of UAA. It needs not be explicitly mapped to any Role Collection.",
		"scope-references": ["user_attributes"]
	}, {
		"name": "Helpdesk",
		"description": "Users who can view configuration.",
		"scope-references": ["$XSAPPNAME.clientlog_read", "$XSAPPNAME.pushregistrations_read", "$XSAPPNAME.admin_read"]
	}, {
		"name": "Administrator",
		"description": "Users who can edit configuration.",
		"scope-references": ["$XSAPPNAME.clientlog_read", "$XSAPPNAME.pushregistrations_read", "$XSAPPNAME.admin_read", "$XSAPPNAME.admin_write"]
	}, {
		"name": "SinglePushUser",
		"description": "Users who can push to one user in one call.",
		"scope-references": ["$XSAPPNAME.pushregistrations_read", "$XSAPPNAME.push_single"]
	}, {
		"name": "MultiplePushUser",
		"description": "Users who can push to multiple users in one call.",
		"scope-references": ["$XSAPPNAME.pushregistrations_read", "$XSAPPNAME.push_single", "$XSAPPNAME.push_multiple"]
	}, {
		"name": "FullPushUser",
		"description": "Users who can push to all users in one call.",
		"scope-references": ["$XSAPPNAME.pushregistrations_read", "$XSAPPNAME.push_single", "$XSAPPNAME.push_multiple", "$XSAPPNAME.push_all"]
	}, {
		"name": "BetaTestUser",
		"description": "Users who can receieve a staged version of an application.",
		"scope-references": ["$XSAPPNAME.access_staged_app"]
	}, {
                "name": "appuser",
                "description": "Required to perform create, read, update and delete api calls",
                "scope-references": [
                 "$XSAPPNAME.appuser"
                ]
        }],
        "role-collections": [{
		"name": "appuser",
		"description": "This is a role collection discription.",
		"role-template-references": ["$XSAPPNAME.appuser"]
	}]
	"oauth2-configuration": {
		"token-validity": 43200,
		"refresh-token-validity": 2592000
	},
	"xsenableasyncservice": false
}

 

Notice in the above XML I have put the appuser scope, role-template and role-collection. Other extra thing is the authorities tag. Rest of the configuration is the Mobile services specific. After doing this, the external access to the application APIs should work.

Now, the question is should you really do this much to get the external app access, and the answer is for now there is no other way as Mobile services upload xs-security.json file does not consider the ‘authorities’ tag. It is only restricted to ‘scopes’, ‘roles-templates’ and ‘role-collections’.

Assigned Tags

      1 Comment
      You must be Logged on to comment or reply to a post.
      Author's profile photo Sunil Lal
      Sunil Lal

      Could you take a relook at the blog statement above "Before creating the XSUAA Service instance prepare the xs-app.json file"? Did you mean "xs-security.json"?