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: 
boudhayan-dev
Employee
Employee
In this blog post we will see how we can configure OAuth2 authorization for a Spring Boot application in SAP Cloud Foundry environment. But before doing so, let us get ourselves familiar with few important concepts involved in this implementation.

INTRODUCTION


OAuth2 - is an authorization framework. It is not an authentication protocol ( Ref - Authentication vs Authorization ). The authentication is actually carried out by the IdP. And in our case (SAP CF), it is the SAP ID service (default).

JWT - JWT stands for JSON Web Tokens, which is a standard for representing claims between two parties securely. OAuth2 uses JWT tokens as a means to convey the authorization information.

XSUAA - XSUAA is a service available on SCP-CF which used to provision roles, groups and role collections to users. It will be used together with the SAP ID Service to authorize users to access our APIs.

Approuter - Approuter is a NodeJS app provided by SAP. It forms the single point of entry for all your applications - Backend and UI. This service eases the Authentication and Authorization flow. Internally, this service is responsible for calling the IdP and XSUAA services to validate a user request. As an end user, you just need to call the deployed approuter application's URL and that will in turn navigate to Authentication endpoint or to the resource directly if already authenticated.

The authentication flow that takes place in SAP CF is as follows -



Let us setup our application now.

DEVELOPMENT


The code samples used in this blog can be found here - GitHub

To demonstrate the usage of XSUAA service, we will create a sample application with the following objective -

We will create a Movie Booking service, similar to applications like BookMyShow. In our application, we will have 2 roles - Manager and Employee. Manager will be responsible for Creating, Updating and Deleting movie listings and Employee will be responsible for performing ticket reservations for the existing movies. The employee shall not be able to Create, Update or Delete the movies. They can only read the already existing movie info. The manager however is like a super admin and has access to the roles of employee. 

Now with this scope, let us start creating the app.

1. Create XSUAA instance on SCP.

Create a XSUAA service with the name - spring-xsuaa-cf-uaa on SCP. Assign the following code in 'Specify parameters' section. The following code describes the 2 scopes that we have defined - Employee and Manager. We will create role templates, with the same name as well. 

xs-security.json -

{
"xsappname": "spring-xsuaa-cloud-foundry",
"description": "Roles for spring xsuaa app",
"tenant-mode": "shared",
"scopes": [
{
"name": "$XSAPPNAME.Employee",
"description": "Employee scope"
},
{
"name": "$XSAPPNAME.Manager",
"description": "Manager scope"
}
],
"role-templates": [
{
"name": "Employee",
"description": "Role for employee to read movie listings and update reservations",
"scope-references": [
"$XSAPPNAME.Employee"
]
},
{
"name": "Manager",
"description": "Role for manager to create new movie listings and remove existing ones",
"scope-references": [
"$XSAPPNAME.Employee",
"$XSAPPNAME.Manager"
]
}
]
}



2. Spring Boot Application


I have used MongoDB (Mongo Atlas) for persistence. Mongo Atlas provides a free tier as well. In the following section I'll briefly explain what's going on in the various section of the java code.



  • Controller - The controller logic can be found here. MovieControllerEmployee and MovieControllerManager are 2 controllers for Employee and Manager respectively.

  • Repository - The repository logic can be found here.

  • Model - The model definition for Movie document can be found here. It describes a document that has properties like - name, description, airing date and total seats available.

  • Config - The configuration needed for setting up the OAuth functionality can be found here. This file is used to set up how our application URLs can be accessed. The  antMatchers are used to specify the kind of access we are providing to our APIs.

    • antMatchers("/manager/*").hasAuthority("Manager") = This restricts all the APIs starting with manager to be accessible only by those who possess the Manager role.

    • antMatchers("/employee/*").hasAuthority("Employee") = This restricts all the APIs starting with employee to be accessible only by those who possess the Employee role.

    • antMatchers("/local/*").permitAll() = This is used to provide access to Local Token generation endpoint. More on this later.

      Note -
      We make use of cloud-security-xsuaa-integration library for the OAuth handling.



  • LocalEnvironment - Since we have protected our endpoints in the config file with the relevant scopes, it is not possible to access them while developing locally without providing proper token. To solve this, cloud-security-xsuaa-integration library provides utility functions to generate this token locally. The code for this can be found here. The two classes are -

    • MockEnvironmentProcessor - This provides XSUAA server like capability while developing locally. It will generate and validate access tokens for local development. This should never be used in production. To prevent it from being accidentally activated in the Cloud, we have protected it with a profile called - uaamock . Whenever, the application is run with this profile locally, it will be activated. But when we push the final project onto the cloud, this profile should be deactivated.

    • LocalTokenGenerator - This is a helper controller class that I have created to get access token in development. The code is self-explanatory. I have provided both Manager and Employee scope for unrestricted access during development. This controller is also available only when run with profile - uaamock. 




For detailed information on the available endpoints and how to access them, please refer the README.

3. AppRouter

In this section we will set up the application router that will handle all the incoming requests.

Create a package.json file with the following content -
{
"name": "approuter",
"dependencies": {
"@sap/approuter": "3.0.1"
},
"scripts": {
"start": "node node_modules/@sap/approuter/approuter.js"
},
"engines": {
"node": "8.16.0"
}
}

Run npm i in the folder to install all the dependencies.

Create another file called xs-app.json -

This defines the way we can access our API in the c
{
"routes": [
{
"source": "^/xsuaa",
"target": "/",
"destination": "spring-xsuaa-cf-destination"
}
]
}

loud. xsuaa prefix needs to be used. Example - <<ROOT_URL>>/xsuaa/employe/movie/list. 

DEPLOYMENT


With all the development artifacts in place, we can now deploy our app. For deployment, we use the manifest.yml file - It can be found here.

Use cf push to deploy the application.

Once the app is deployed use -
cf map-route spring-xsuaa-cloud-foundry-approuter cfapps.sap.hana.ondemand.com -n <<subaccount_name>>-spring-xsuaa-cloud-foundry-approuter


 

With this we, have deployed our application to cloud. Now the only step remaining is to assign role templates to our users. To assign roles, navigate to Role Collection in subaccount and create a new collection. Assign the roles that you want to provide in that collection as follows -



Now, we have to assign this role template to an actual user. Navigate to Trust Configuration and assign the previously created template to an user (use email) as follows -


TESTING


To test this application, open the Approuter application and visit its URL. It will prompt you for login.To test the APIs, follow the README link attached above.

In the above step, I have only provided Employee role to myself. As a result I will only be able to access the APIs listed for Employee role. If I try to access Manager role, I will get a 403 unauthorized error.

You can test the APIs via browser. However, there maybe scenarios where you'd need to make POST/PUT calls with a request body. In that case you'll need to use a REST client like POSTMAN. However, you cannot use the Approuter link directly in POSTMAN, as it cannot process the redirect from XSUAA login to resource url. For this, we would need to call the JAVA backend's API directly (without the redirection from approuter).

To do this, we would need a valid token to to access our APIs. Proceed as follows -

  1. Access the VCAP_SERVICES environment variable of the backend application by using -
    cf env spring-xsuaa-cloud-foundry​

     

  2. Copy the url, clientid and clientsecret under the xsuaa section. We will use these credentials to get a valid access token.

  3. Make a POST call to the url (url + "/oauth/token")  obtained above with the following parameters -



    grant_type = password
    username = email ID
    password = password
    client_id = obtained from VCAP_SERVICES
    client_secret = obtained from VCAP_SERVICES
    response_type = token

  4. You will receive an access token in the response body. It will also contain the scopes assigned to your user.

  5. Use this access token (as a bearer token) for all the API calls to your backend.



 

 

For more details about all the available APIs and how to access them, follow the README.

With this, we have configured OAuth in our application and have secured our endpoints with role based access.

 

Regards,
Boudhayan Dev
12 Comments