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: 

Introduction


Before we start this long article let me introduce myself (LinkedIn😞 I am currently working as a Cloud Solution Architect within SAP IEG (mostly known as SAP IT) in a so-called Platform CoE team. We are maintaining and running the SAP IT cloud accounts (with 100s of applications) and assure that all our internal cloud tools are running flawlessly & help easing the daily life of every SAP employee with these applications and tools.

Another big topic within our team is sharing cloud development and operation knowledge across SAP IT and defining best practices how to develop tools and applications within the given constraints of our large existing infrastructure and processes.

My colleagues and I are doing a lot of classroom trainings around the globe, writing technical articles and mentoring teams as on-demand consultants to overcome the challenges that might happen when developing applications for SAP Cloud Foundry.

Guess what!? The most questions coming up are in regards to authentications and authorisations within SAP Cloud Foundry as this is a always a complex and sensitive topic.

Within our classroom trainings we have a really long chapter about “XSUAA“ (extended services for UAA). All our participants are happy afterwards that they now have the basic knowledge to protect their applications and offer secure applications to their users. This is the reason why we decided to share some of this knowledge on this blog post and maybe help also other people outside of SAP to demystify XSUAA and the overall topic of “Protecting and securing upcoming cloud applications“.

Just a disclaimerWe are NOT working in the XSUAA dev team. This article might already contain outdated elements & facts to be taken with a grain of salt. If you think something is not right please let us know in the comments and we will update the article(s) accordingly – and of course learn something new – even more important!

SAP is offering a great help page about XSUAA (https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/6373bb7a96114d619bfdfdc6f50...) and this article should act more as a summary than as some kind of a reference. Always double check the info in this article with the help page!

A big thanks goes out to all the XSUAA colleagues helping us the last years (!) in a LOT of sessions and meetings with all our questions and problems. Without their help and patience an article like this & a lot of classroom trainings would have never been possible!

Even though this article is published with my account, the different parts of this article has been written with the help of johannes.staehlin, pranjal.chugh,julian.breuksch and alexandra.hofmann who also work in my team, travel around the globe sharing their knowledge with other fellow colleagues and writing a hell of sample apps & articles to ramp up developers and account owners for their future SAP Cloud Foundry applications.

Business-Users (XSUAA) and Platform Users (UAA)?


There is a difference between these users. The official help (https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/51ec15a8979e497fbcaadf80da9...) page states:

The Cloud Foundry environment at SAP Cloud Platform distinguishes between two user types and manages each type in a separate UAA instance. This means the two types are completely separated:

  • Platform users perform technical development, deployment, and administration tasks. They use tools like the cloud cockpit and the cf command line client. These users typically have authorizations for certain organizations and/or spaces, and other technical services in the Cloud Foundry environment. Apart from authentication to the platform using the cf command line client, usually there is no direct interaction between users and the platform UAA.

  • Business users only use business applications deployed to SAP Cloud Platform. They do not use SAP Cloud Platform for technical development, deployment, and administration tasks. A business user is always bound to a specific tenant which holds the information about the user’s authorizations. Tenants, business users, and their authorizations are managed by another UAA instance using the extended services for UAA (XSUAA). This component additionally provides a simple programming model for authentication and authorization in business applications.


What is the XSUAA and the UAA?


Before we explain how you can protect your applications within Cloud Foundry it is important to understand the difference between the UAA and the XSUAA.

The UAA


 

Have a look at the diagram below. Once again there is a huge difference in Cloud Foundry between Business Users (Users accessing Services, Applications and Subscriptions) and Platform Users (Users that administrate the Cloud Foundry account and its security). The UAA is technically not WITHIN the Cloud Foundry instance, but rather a requirement to get Cloud Foundry running. So after an administrator has configured a Cloud Foundry instance he is forced to also configure a server that is taking care of users trying to administrate this instance via oAuth2. And that's the UAA. As a developer you won't work directly with the UAA, but rather with the XSUAA.

 



The XSUAA (eXtended Services for UAA)


 

The XSUAA is one of the most important component to deal with when developing your own applications on Cloud Foundry. It takes care to authenticate and authorise your business users and assign the right principals to your user's session so your application can:

  • Identity the user by Email, UserId, First and Lastname

  • Check his roles (scopes) to decide if a user is allowed to do something or prohibit is action


The XSUAA is an internal development of SAP. SAP took the base of the open source UAA Oauth2 Provider of Cloud Foundry (https://github.com/cloudfoundry/uaa) and extended it with SAP specific features to be used in SAP applications. One important thing is that the XSUAA does NOT store "real" users. This is why the XSUAA needs to trust an external Identity Provider (short "IdP"). But how does a user get his roles and the appropriate rights to access your applications? Before we explain the rough concepts let first look at the terms and their relationship to each other: Role-Collections, Roles and Scopes. These terms are introduced by the XSUAA within Cloud Foundry.

Role-Collections, Roles and Scopes


Protecting your applications is all about using Role-Collection/Roles and Scopes. In the following diagram you find the relationship between the different entities. It starts with modelling your roles and scopes during development and ends with an assignment to a role-collection thats further been assigned to a certain business user. The XSUAA will store all the information about these entities in its database. So whenever you want to model your roles and scopes you need to create within the XSUAA a so-called "xsapp". Just think of that you create within the XSUAA a certain area that is especially reserved for you application where you can put all your security stuff in (you will do this when creating an instance of the XSUAA service in the marketplace and provide a xs-security.json - see https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/150b04d647cd4b42835411c1787...

Look at the following diagram that will show the relations between all the mentioned entities:


 

Scopes


 

Scopes are arbitrary values that express authorisations / access rights an an application or service. Scopes need to be prefixed with the "xsappname" to make them uniquely identifiable. Scopes are what your application later on needs to validate and are put in a JWT on each request to your applications (we explain this later). In the diagram you can see that scopes are really granular things that might be mapped to your CRUD actions like "creating", "updating" or "deleting" entities in your backend. But you are not forced to follow this approach. For example in a lot of applications we use the scope "admin" to simplify things. All the scopes needs to be assigned during development to another container-entity: a role. 

Roles


 

Roles are an entity that will hold all your scopes. Scopes can be put in multiple roles so you are not limited to have scopes sitting just in one role. For example - looking at the diagram - it might be possible to put the ARTICLE.UPDATE scope in the ContentCreator and Reviewer role as both roles might involve the editing of an article in your application. During the modelling/developing of the roles you are technically modelling a so-called "role-template" as you might leave out attributes (https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/517895a9612241259d6941dbf9a...) that can be bound to assertions or static values been filled by the XSUAA or an admin later when it needs to be assigned to a role collection (that's a rare case. In 90% of the cases we use "role-template" in analogy to a "role").

Role Collections


 

Now comes the interesting part 🙂 Role-Collections contain one or more roles. A role can be in multiple Role-Collections. But it is totally fine to have eg a role-collection been called "Admin" only having an "admin" role.

Role-Collections are stored as an assignment in the XSUAA and are THE entity that can be assigned to a certain business user. During runtime the XSUAA will loop over all Role-Collection assignments and will then wander the virtual path from a Role-Collection over a role down to a scope to put all the scopes that a user should have within the JWT been forwarded to your applications.

As we know now the most important entities, let's explain how YOU can create them and assign them to your users!

But how to create Roles and Role-Collections and assign them to users?


The following chapter is a short summary of the official help page (https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/7c5c565f37c946faa1549090043...).

In the diagram you can see that we have multiple personas. One is the developer working within a project and within his space. The other persona is an admin taking care of the CF account as a security admin (this is a special platform role that can be maintained by admins in the cockpit)


The * might indicate that in the future the provisioning of these role collections might be automated by SAP IDM.

What is a xs-security.json?


 

To simplify things, let's just call a xs-security.json the "declaration of your app's security". The following xs-security.json is an excerpt of one of one of our training exercises we use within our classroom trainings (do not be confused about the appname, within the training we develop a small interactive hangman game ;)).
{
"xsappname": "hangman-app",
"tenant-mode": "dedicated",
"scopes": [
{
"name": "uaa.user",
"description": "UAA"
},
{
"name": "$XSAPPNAME.playHangman",
"description": "Allows to play hangman games"
}
],
"role-templates": [
{
"name": "Token_Exchange",
"description": "UAA",
"scope-references": ["uaa.user"]
},
{
"name": "user",
"description": "User",
"scope-references": ["$XSAPPNAME.playHangman"]
}
]
}

There you can see that you have to tell the XSUAA service how to call your application (xsappname) and further define your scopes and role-templates (to simplify things let's just call them "roles").

Creating an xsuaa application (instance)



  • Login to your SAP Cloud Platform Cockpit.

  • Navigate to your space and select Services > Service Marketplace.

  • Click on the service Authorization & Trust Management and navigate to Instances.

  • Create a new instance, choose a plan (in 95% of all the cases it's plan application) and provide the content of your xs-security.json as a parameter.


What are all the different plans when creating an instance?


 

The plans are telling the XSUAA service what kind of xsuaa application you want to create. The plan makes a huge difference in the behaviour and use case. To make it short and simple and we are just talking with our own experience - in 90% of the case the application plan is sufficient.

Even though you do not need your xs-security.json within the code of your application we strongly encourage you to put it in an up-to-date version in one of your application's repository. This helps during error analysis and debugging to know how your instantiated xsapplication looks like. IT IS NOT POSSIBLE to inspect these values in the CF cockpit at the time this page has been written.

Second part - An admin's (account owner's/security admin's) duty


 

Yay, your developers have done their job, have created with the XSUAA service their own xsapplication and now they want to assign their roles to business users accessing their applications. The bad thing: They can't do this on their own. The good thing: That's your job!

  • Login to your account via Cockpit

  • Navigate to the subaccount, select the Security tab and the Role Collections section.

  • Create your role-collection

  • Navigate into the newly created role collection and add a role by selecting the app identifier with the role/role template been communicated by the developers to you.

  • Navigate back to the subaccount, select the Security tab and the Trust Configuration section.

  • Select a configured identity provider and navigate to Role Collection Assignment.

  • Search for your user and assign the new role collection to the user


For a lot of people it is confusing why you need to choose an Identity Provider before assigning a user to a role collection. But it makes sense, if you know a little bit about how users are handled and why the XSUAA.

Why a CF account needs to trust an Identity Provider (IdP)?


As stated it might be confusing why an assignment of a Role Collection can only be done when choosing an Identity Provider. But it makes sense if you think about customer scenarios where a customer might want to connect his/her own user base to the maintained CF account. It is even possible to maintain multiple Identity Providers to your CF account (and is often a valid scenario in conjunction with an additional Neo landscape). But why do I have to choose an IdP when assigning a role collection? 


 

There you see that a XSUAA is trusting several IdPs. And each IdP has its own user base storing the business users. So what the XSUAA is doing whenever someone needs to make a login on top of your application and therefor configured xsapplication? It will forward the user to a configured IdP.

The IdP will take care of the login and will return a SAML Assertion (containing a certificate of the IdP - that's exactly why you need to configure the trust) describing the user with an ID and providing additional information (like FirstName, LastName, Email, etc.) to the XSUAA.

The XSUAA will then take this UserID and check within an internal table for your xsapplication if there are any assignments made for the chosen IdentityProvider for the given UserId. See the following table to get an idea of the assignments.


So the reason why you have to choose an IdentityProvider when assigning a RoleCollection is just, because the XSUAA does not store your IdP's user, but rather "an ID" been provided by the IdentityProvider after login with a SAMLResponse.

But how can all the scopes and user information been transported to your applications? 

That's been done in a special format in all the http request headers via a so-called JWT. The XSUAA will take the user information after login by the IdP (because he receives the SAML Assertion) and combines this with the Role Collection assignments and all the scopes bound to it for the given xsapplication. The combination will then be put in a JWT that can be added to your http requests targeting your applications and services.

What is a JWT?


As stated in the previous chapter a common use case for a JWT (JSON Web Token) is a SSO across multiple applications and services. A full introduction can be found here.

All the specifications put apart there are two things you need to know. A JWT consists of three main components that are declared as plain JSON:

  1. header: Declaration of the used hashing and signing algorithms

  2. body: Might be anything, but in our case it is the information about the user, the issuer and all the scopes.

  3. signature: The signature allows the integrity of the JWT. The XSUAA will put the header of the ticket together with the content


All these parts can then be combined together and converted with base64 so its easier to add them in other data structures:


But that's what the XSUAA does for us. So the XSUAA acts as the central administrator creating dedicated & tailored JWTs for our created xsapplication we have built when creating our XSUAA service instance via the marketplace. And no one else is able to do this. At least we should not trust anyone else.


Where to add a JWT in the request?


 

To access a protected Oauth2 Resource it is common usage to add an access token to the HTTP Authorization Header as a Bearer (https://tools.ietf.org/html/rfc6750#page-5).
This can easily be done with REST clients like Postman (https://www.postman.com/) and YARC (https://chrome.google.com/webstore/detail/yet-another-rest-client/ehafadccdcdedbhcbddihehiodgcddpl). If you have protected resources that will need a JWT in the header, that's the way to go.

And how do I know if the JWT is valid?


 

A JWT always needs to be validated. As already stated only the XSUAA component in your account can be trusted as an issuer of the JWT. To validate a JWT you need to check its signature (remember: Every JWT is signed with the private key of the issuer - in our case the XSUAA). So you need to take the public key of the XSUAA and check if the signature can be validated with this public key. But how can you get this public key?

Offline Validation


 

The easiest way to get to a public key is by binding the created XSUAA instance to your application. Within the binding you can then find the public key of the XSUAA component within your account (identity zone). You can now take the public key, use the algorithm out of the JWT header and validate the JWT. Look at the following image that is just a screenshot of one of the XSUAA instances within an example project.



JWKS validation


 

Within the header of a JWT you can also add additional information about where the consumer can get a public key to validate it (https://tools.ietf.org/html/rfc7517). This concept is called JWK. So you can take this URL, extract the kid (key id) from the JWT and download the public key for a further validation. You might already get it: you need an additional round trip to download the key and cache it somewhere. The advantage is that you always have the most updated public key. The disadvantage is, that you need the round trip AND you are not allowed to just follow the URL blindly. Why are you not allowed to follow this URL blindly? Because anyone can create a valid JWT, put his own URL in the header with a valid public key and then you would take this false key and have a once again a valid key that is manipulated.

How can you circumvent this? By hard coding the JWK url somewhere in your application and check if the URL (in essence the host) in the JWT corresponds to the URL (you trust) and have hard coded in your source. Hard coding a URL in the source code will be a problem, because the URL will change from environment to environment (DEV - TEST - PROD), Guess what!? The host (URL) can also found in the XSUAA service binding.

You can find the public keys by either using the jku-Property in the JWT


or just adding /token_keys to the URL you find in the binding. Then you can see the public keys available and use them for validation




Which libraries to work with a JWT and how can I validate it?


 

Wow. This sounds like a lot of work! Thanks to the openness and specification of JWT and JWKS there are a lot of libraries available to work with (https://jwt.io/#libraries-io). But most of them require additional work. So in most of the cases you have to take care of parsing the JWT, getting the public key from JWK url and validating it. Of course these things are not THAT complicated, but often end in boilerplate code.

SAP is offering its own XSUAA libraries (including offline validation and caching the JWK public key) that will make it really easy to add it to your services and take care of your service protection and validating the JWT: https://github.com/SAP/cloud-security-xsuaa-integration

Things you should know about working with a JWT



  • A JWT is NOT encrypted. At least not those coming from our XSUAA. Most of the communication will be made "internally" within the Cloud Foundry network using the AppRouter. Due to that an encryption is not needed.



  • You should NEVER expose the JWT been used in your requests to public. We know that it is sometime useful to see the content of a JWT to debug problems, but there are other ways to inspect the JWT than having a REST service returning or logging the JWT.

  • Validate the signature: Whatever you do with the JWT DO NOT WORK WITH IT WITHOUT VALIDATION!! Anyone can create a JWT and just add to the headers of the http requests. If you are not validating the content, anyone can pretend to be person XYZ with scopes ZYX!

  • Do not take the JWK as granted: You should always compare the hostname of the jku in the JWT with the hostname of your XSUAA service binding URL. 


What are the most common flows to get a JWT?


Great. Now you understand that a JWT from the XSUAA is the way to allow authenticated SSO and protect your services against. So with the SAP XSUAA (https://github.com/SAP/cloud-security-xsuaa-integration) library you followed the examples and protected your web service. But how can others (and your frontend) now access it? How can your applications retrieve this JWT so that they can add it to the request been sent to the protected backend?

As said a lot of times the XSUAA component will give you this JWT via a mix of oAuth and SAML flows. And there are - simplified - two essential options how the XSUAA will provide you a JWT:

  • Client Credential Grant

  • Authorization Code Grant


Whilst the Client Credential Grant will only give you a JWT without ANY information about the user accessing your application the Authorization Code Grant includes the user information (and therefor the information the trusted Identity Provider will deliver as a SAML assertion). Both flows are supporting different use cases (technical users or user principal (with all the user information))

How can I interact with the XSUAA?


 

The XSUAA is providing an official API that will allow you to interact with it and eg ask for a valid JWT. But to interact with it you need a technical user and password. It is pretty easy to get this: By creating an XSUAA instance within your space. The resulting binding (or service key) of this instance let you see the technical user - clientid -, the password - clientsecret - and the API url (see the following image as an excerpt from the XSUAA binding within the cockpit).


With this information you can now interact with the oAuth API and retrieve your JWT.

Client Credential Grant


 

The Client Credential Grant will provide you a JWT with only the information of the technical user been created to interact with the API. This technical user might be reused by your application wanting to access your backends IF you are not interested in the user principal (the current logged in user), but rather been interested if a technical user (that you created with your xsuaa instance) has been used for authentication. So the client credential flow is often used for use cases that does not involve any concrete user information. 

Obtain a JWT with Client Credential Grant


 

Use the the following URL of your XSUAA instance (just an example XSUAA): https://accountid.authentication.hana.ondemand.com/oauth/token?grant_type=client_credentials and enter the clientid and secret when prompted for a basic authentication (in a technical implementation you will already add these details to the basic auth header!). You will get the JWT in the response. This JWT can now be added to the HTTP request header (authorization bearer) been targeting your protected backends. But remember: This JWT will not have ANY information about the user been accessing your application. It only assures that "someone" has access to your technical user and the password (what might be sufficient for a lot of use cases!).

Authorization Code Grant


 

The Authorization Code Grant will provide you a JWT with user information (Who is accessing your backend? Name? Email? First Name? Last name?). The user information is been provided by the identity provider the user chooses for his login and the XSUAA is trusting within your account. The XSUAA will take this information and put it in the JWT been given out to the requester.

Obtain a JWT with Authorization Code Grant


 

The JWT retrieval consists of two parts:

  • Login at the IdP and create a dedicated authorization codeOnce again you will use the client id, secret and xsuaa URL of your XSUAA instance. An example might look like this: https://acountid.authentication.hana.ondemand.com/oauth/authorize?response_type=code&client_id=yourc... XSUAA will redirect you to the chosen IdP and you either need to login with your username and password or in the case of SAP IdPs you are automatically signed in with your SSO certificate. When you got logged in, the IdP will send a SAML assertion with all your user principals back to the XSUAA and the XSUAA will redirect you afterwards to an URL with a authorization code.

  • Use this code with your client id and secret to request a JWT from the XSUAA https://accountid.authentication.hana.ondemand.com/oauth/token?grant_type=authorization_code&code=11... is an example URL that you need to adjust to your needs. You can see in this url the authorization code you received when doing the first step. When doing the request in your browser you will be prompted once again in a basic authentication form to provide your clientid and secret. If everything went fine, you will receive a valid JWT with all your user information.


This JWT can now be attached to your HTTP requests (via authorization bearer header) going to the protected backends and they can extract the user details out of it.

How the Approuter will minimise your work when working with secured applications?


Reading all the chapters (especially the retrieval of the JWT) you might be overwhelmed by the effort it needs to get a JWT and send them to your backend with each call that's been made with your consumers. SAP thought exactly the same and developed an application that should be part of every Cloud Foundry architecture: The Approuter (https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/01c5f9ba7d6847aaaf069d153b9...)

To make it short: The Approuter is a central component and acting as a gateway to all your deployed applications within your space. With some small configurations it is possible to let all the described flows of obtaining a JWT been taken care by the Approuter. So it is not your implementation effort anymore, but rather the Approuter's one. The Approuter will dispatch your requests and add the internal obtained JWT to all the requests going to your backends and services.

Fin


We hope you enjoyed this article and we could clarify some things so you might now understand the concepts of XSUAA and am able to start developing your own secure SAP Cloud Foundry application.

Feel free to check out my profile here or have a look at my LinkedIn profile. Do not hesitate to ask drop me a direct message, if you want to have a small chat or have questions to this or any other blog post.

 
50 Comments