The XSUAA Mystery

For all of you not as familiar with the SAP Cloud Platform, XSUAA is the User Authentication and Authorization service of the SAP Cloud Platform. Unless you want to have applications open to the world, you will need to make use of it to restrict access to your application. That was the starting point for me to figure out what it does and what I have to do to use it properly.

The first confusing thing is the XS in front… well, talk about history: The more you look behind the scenes, there more you feel the SAP Cloud Platform stack started out as a HANA box in the cloud (I know I oversimplify), some of the names got dragged along. This service should probably be called UAA or CFUAA for Cloud Foundry by now… but I digress.

The XSUAA can be triggered or used in various ways. At the moment I use it primarily in the app router (xs-app.json) to secure certain URL path’s. Those URL paths then are assigned to what’s called a “scope”. I think of a scope as a security object. An example definition might look like this:

{
"source": "^/admin/(.*)",
"target": "/admin/$1",
"authenticationType": "xsuaa",
"scope": "$XSAPPNAME.standard",
"destination": "ms-example-srv_api",
"csrfProtection": true
},

When you create a XSUAA service you have to specify a configuration file called xs-security.json. I usually put it into a separate sub directory called ‘security’. That file lists the different ‘scopes’, ‘roles’ and ‘role templates’ this UAA instance is exposing. One role can have one or multiple scopes.

Here is an example of one of my xs-security files (what I have learned as good practice is to overwrite the xsappname with a new name in the MTA, that includes the space):

{
	"xsappname": "ms-example",
	"tenant-mode": "dedicated",
	"foreign-scope-references": [
		"$ACCEPT_GRANTED_SCOPES"
	],
	"description": "Security profile for Example",
	"scopes": [
		{
			"name": "$XSAPPNAME.admin",
			"description": "Example Administator"
		},
		{
			"name": "$XSAPPNAME.standard",
			"description": "Example Standard User"
		},
		{
			"name": "uaa.user",
			"description": "uaa.user"
		}
	],
	"role-templates": [
		{
			"name": "ms_example_standard",
			"description": "Example User",
			"scope-references": [
				"$XSAPPNAME.standard",
				"uaa.user"
			]
		},
		{
			"name": "ms_example_admin",
			"description": "Example Admin",
			"scope-references": [
				"$XSAPPNAME.standard",
				"$XSAPPNAME.admin",
				"uaa.user"
			]
		}
	]
}

To assign a role, you can go into a the cockpit and assign them. I will not go into the details how as it differs depending on what your configured Identity provider is. I started out with the SAP ID Service (you specify the S username and password to login) and we are now using the SAP IAS (Identity Authentication Service). A long story in itself, but I like the IAS and the options it provides… coming back to that later….

How does it work?

In simple terms, xsuaa is jumping in when you need authentication and authorization done. This usually happens in one of two ways:

  1. You are redirected to a logon screen that asks you for your credentials (usually username or email address and password) and then you are redirected from there back to your original target.
  2. You have a service-key or api-key and you make the requests.

Behind the scenes XSUAA complies with OAUTH2.0 and eventually issues you a token that you can use for subsequent requests to your ‘real’ application to insure you are you and are authorized.

The approach works really well if you follow the first way outlined above. You can specify a variety of Identity Providers. The direction to your IDP and redirection to your target work well and you can customize the authentication page if you choose so.

Rather than using the SAP ID service, we switched to using SAP’s provided Identity Authentication Service (IAS) as the standard for most cloud based test and development systems. I like it and it should allow us in the future to simply define a further re-direction to Azure as corporate IDP.

When you choose to access your application through a program it get’s more interesting. Again you should have two options. I will outline the options in a Rest Client conform format. The general idea is that I do one or two calls to receive an access token which I will subsequently use to access the application like this:

GET [Target Server][your service]
Authorization: token [token type] [access token]

Before we can do that we need to get the access token, so let’s try to get that.

Access using grant type ‘password’

There are a lot of examples out on the web that describe this approach and the request should look like this:

POST https://xxx.authentication.us10.hana.ondemand.com/oauth/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Authorization: Basic [your username]:[your password]

grant_type=password
&response_type=token
&username=[your username]
&password=[your password]

This should work as long as you are using the SAP ID Service.

If you are using the SAP Identity Authentication Service (IAS) I receive

{ "error": "unauthorized", "error_description": "Bad credentials" } 

After days of searching the web, I finally found SAP note 2766354 (https://launchpad.support.sap.com/#/notes/0002766354) , which says what I am trying to do is not supported. Please use SAP ID service… mhh, that would defeat the purpose of having switched to IAS to begin with…

So on I go and try the access key approach.

Access using the grant type ‘client credentials’

In order to perform this access you need to request a service-key. What you really need is a client id and a client secret. You can a) create create a service-key through the command line and find client id and client secret b) create a service key through the Cloud Platform Cockpit or b) simply look at the sensitive information of one of your applications binding to the xsuaa service

Scarily the client id and client secret is the same for all approaches and for all instances of a service key. Call me secure conscious, but that cannot be correct.

The request that I use is the following:

POST https://xxx.authentication.us10.hana.ondemand.com/oauth/token HTTP/1.1
Authorization: [client id]:[client secret]
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials
&response_type=token
&client_id=[client id]

I receive a response with token! I am all excited as this seems to be a solution. When I use the token to access my service, I am disappointed, as my application will not execute and instead returns a html page with an authentication request… but I submitted a token.

So now I am two for two when it comes to successes in accessing my application.

This is where I give up having already sunk 3 days on and off digging into it and submit a ticket to SAP. I will update this blog with what I get back or what I find.

The outstanding questions I have and hope to get answers to are:

  1. Is SAP really not supporting IAS when I programatically want to access my application through grant_type ‘password’? I would assume that IAS should be a very common IDP these days that SAP would support their own IDP.
  2. Given that this access token is not associated with any user, what scopes does it have associated?
  3. Why are service keys not
    • unique for a certain id?
    • limited to certain scope?
    • limited to a time period?
    • cannot be revoked if you delete the service key?