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: 
showkath_naseem
Product and Topic Expert
Product and Topic Expert
5,952

Introduction:


Hello everyone,


In this blog post, I want to share my recent experience with upgrading to Java 17 and Spring Boot 3.X on SAP Business Technology Platform (BTP). With the latest SAP Cloud Security 3.X Library, there have been some significant changes.

Specifically, I'll be focusing on a crucial use case – how to fetch Current Logged-on User Details in various applications such as Java, Spring Boot, CAP, NodeJS, and SAPUI5. Let's dive into the details and explore the process step-by-step.

Stay tuned to learn how to make the most out of SAP BTP and enhance the security of your applications. Let's get started!

Purpose:


Before we dive into the technical stuff, let me explain a few essential BTP Security Concepts briefly. It's good to be familiar with these concepts to understand the process better. If you already know them, feel free to jump straight to the main part of the blog, where I'll show you how to get the Current Logged-on User Details in various technologies from BTP.


The Reason Behind This Blog Post:
You might be wondering why I'm writing about something that already has a lot of information available. Well, the existing content mostly covers older libraries, and with the latest SAP Cloud Security 3.X Library, things have changed.


So, I want to demonstrate the most up-to-date approaches to help you stay current with the best practices in BTP Security.



Main Takeaways:


Now, let's break down what this blog post will cover into three parts:




  1. Quick Overview of SAP BTP Security Concepts:
    I'll provide a simple explanation of essential security concepts in BTP.

  2. Understanding Deprecated and Successor Elements:
    We'll see which security elements are deprecated and the newer, more secure options available.

  3. How to Get Current Logged-on User Details:
    The main focus will be on the step-by-step process of fetching Current Logged-on User Details using the latest SAP Cloud Security 3 Library in Java 17 and SpringBoot 17 applications.


Additionally, I aim to make this blog post your go-to resource for getting Logged-in user details for CAP, NodeJS, SAPUI5/HTML-based applications from BTP.



1) Quick Overview of SAP BTP Security Concepts


SAP BTP Identity Providers:




  • SAP ID Service: Default Identity Provider provided by SAP, which handles user authentication.

  • Identity Authentication (IAS) Service: Custom Identity Provider for user management and authentication. Offers a centralized user management option for SaaS providers.


Advantages of Using SAP IAS for SaaS Applications:




  • Centralized user management for all SaaS consumers.

  • Customizable onboarding and user experience.

  • Allows integration with consumers' own Identity Providers.


Authorization and Trust Management (XSUAA):




  • XSUAA server controls authentication and authorization in SAP BTP, Cloud Foundry.

  • Issues JWT tokens with scopes and attributes.

  • Delegates user authentication to the connected IdP.


Application Router (APPRouter):




  • Acts as the single entry point for applications in the Cloud Foundry environment on SAP BTP.

  • Serves static content, authenticates users, and forwards requests to microservices.

  • Utilizes xsuaa service for access tokens and identity service for OIDC tokens.


Managed Application Router:




  • SAP-managed application router provided for most cases.

  • Self-managed application router recommended for advanced cases or extensibility requirements.


For detailed information, refer to the official SAP Help :




Blog Posts

 

2) Understanding Deprecated and Successor Elements:


Deprecated SCIM REST API documentation can be found at:
SCIM REST API (Deprecated)

Successors




















No. Successor Description
1 SAP Authorization and Trust Management Service in the Cloud Foundry Environment

Use SAP ID service as a pre-configured easy-to-use identity provider. Switch to your corporate identity provider for customized user management.

Additional Information:
Platform API Overview
2 Identity Directory Service API Information published on SAP site A comprehensive Cloud Identity suite of services such as Identity Authentication or Identity Provisioning.
To secure cloud-based access to business processes, applications, and data. It simplifies your user experience through state-of-the-art authentication mechanisms, secure single sign-on, on-premise integration, and convenient self-service options. Identity Authentication provides implementation for the System for Cross-domain Identity Management.
IAS can provide central Authentication and SSO.
Customers can have only one IAS tenant. Hence all the SAP cloud solution as well as BTP will be integrated with the same IAS tenant. Now, IAS itself has capabilities to have user details including roles, user group, etc. While implementing SSO and application security, we can map a BTP role collection to a user group based on which user authorization works.Additional Information:For detailed information, refer to the official SAP Help :Cloud Identity Services CommunityBlog Links:SAP BTP Security: How to Handle Authorization and Attributes with XSUAA and IAS

Deprecated Libraries


As updated in the GitHub repository, the spring-xsuaa library is deprecated and will be removed with the next major release (4.x). It is advised not to use it for new projects. Instead, follow the migration guide to switch to the successor spring-security library.
<groupId>com.sap.cloud.security.xsuaa</groupId>
<artifactId>spring-xsuaa</artifactId>

Deprecated Imports & Successors













Deprecated Successor

import com.sap.cloud.security.xsuaa.token.SpringSecurityContext;
import com.sap.cloud.security.xsuaa.token.Token;


import com.sap.cloud.security.spring.token.SpringSecurityContext;
import com.sap.cloud.security.token.SecurityContext;
import com.sap.cloud.security.token.Token;


 

Further information:Please use the following link to find further information on the topics above:




3) Getting Logged-on User


3.1) Getting Current User in Java, Spring Boot App, BTP


Include below libraries


<!-- Spring Security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>com.sap.cloud.security</groupId>
<artifactId>resourceserver-security-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.sap.cloud.security.xsuaa</groupId>
<artifactId>spring-security-compatibility</artifactId>
</dependency>
<!-- OAuth2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>




import com.sap.cloud.security.spring.token.SpringSecurityContext; //new 
import com.sap.cloud.security.token.SecurityContext;//new
import com.sap.cloud.security.token.Token;//new
//import com.sap.cloud.security.token.XsuaaTokenComp; or
import com.sap.cloud.security.token.TokenClaims;//new
....

// Sample Method
@GetMapping("v1/currentUserDetails")
@ResponseBody
public ResponseEntity<?> LoginUserDetailsFromAuthenticationPrincipaAl(@AuthenticationPrincipal Token token) {


HashMap<String, String> mapCurrentUser = new HashMap<String, String>();


mapCurrentUser.put("userid", token.getClaimAsString(TokenClaims.USER_NAME));
mapCurrentUser.put("email", token.getClaimAsString(TokenClaims.EMAIL));


String audienceList = StringUtils
.join(token.getClaimAsStringList(TokenClaims.AUDIENCE));
mapCurrentUser.put("audienceList", audienceList);


mapCurrentUser.put("SAPUserID", token.getClaimAsString(TokenClaims.SAP_GLOBAL_USER_ID));


mapCurrentUser.put("xsuaaClientID",
token.getClaimAsString(TokenClaims.XSUAA.CLIENT_ID));

String scopesList = StringUtils
.join(token.getClaimAsStringList(TokenClaims.XSUAA.SCOPES));
mapCurrentUser.put("xsuaaScopesList", scopesList);

mapCurrentUser.put("xsuaaOrigin", token.getClaimAsString(TokenClaims.XSUAA.ORIGIN));


return new ResponseEntity<>(mapCurrentUser, HttpStatus.OK);
}






Please use the following links to find further information on the topics & Read the instructions in the source documentation










3.2) Getting Current User in Java ,Servlet


Example
import com.sap.cloud.security.token.AccessToken;
import com.sap.cloud.security.token.SecurityContext;
import com.sap.cloud.security.token.TokenClaims;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

public class DemoJavaServlet extends HttpServlet {
static final String ENDPOINT = "/hello-java-security";
private static final Logger LOGGER = LoggerFactory.getLogger(DemoJavaServlet.class);

/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
response.setContentType("text/plain");
// same like SecurityContext.getToken() but more XSUAA specific methods
// Same like SecurityContext.getToken() but more XSUAA specific methods
// SecurityContext.getToken()
AccessToken token = SecurityContext.getAccessToken();
String message= "";
try {

message = "You ('" + token.getClaimAsString(TokenClaims.EMAIL) +
"') can access the application with the following scopes: '" +
token.getClaimAsStringList(TokenClaims.XSUAA.SCOPES) + "'. " +
// for authorization check you need the AccessToken interface (instead of Token)
" Having scope '$XSAPPNAME.Read'? " + token.hasLocalScope("display") +
" USER_NAME = " + token.getClaimAsString(TokenClaims.USER_NAME) +
" SAP_GLOBAL_USER_ID = " + token.getClaimAsString(TokenClaims.SAP_GLOBAL_USER_ID);


} catch (final Exception ex) {

LOGGER.error("Failed to write error response: {}.", ex.getMessage(), ex);
throw ex;
}
}

}

Example Response
   

{
"SAPUserID": null,
"audienceList": "sb-xsac-showkathBTPdemo!t99486,uaa,openid,xsac-showkathBTPdemo!99486",
"userid": "P99486", (The user ID in the identity provider),
"xsuaaOrigin": "httpsaccounts400.sap.com", (The Origin in the identity provider),
"email": "john.doe@sap.com",
"xsuaaScopesList": "xsac-showkathBTPdemo!t99486.admin,xsac-showkathBTPdemo!t99486.read,openid,xsac-showkathBTPdemo!t99486.administrator,uaa.user",(Only if the authentication type is “xsuaa")
"xsuaaClientID": "sb-showkathBTPdemo!t99486"(Only if the authentication type is “xsuaa")
}


3.3) Getting Current User in CAP NODEJS


Quick Overview of CAP Security


When running your CAP application, there are multiple types of Authentication Strategies available:




Token-Based Authentication (JWT) is used when your application is deployed to Cloud Foundry. It can easily be integrated with XSUAA. Dummy Authentication may be used to temporarily disable authentication, e.g. during integration tests. Mocked Authentication is the primary choice for development. It allows us to define users locally using passport and easily test the behavior of our different roles.



Basic Concepts


Users may be assigned to User Roles that are either pseudo-roles (authenticated-user, any,..) or map to local/XSUAA roles (admin, employee...). Static Restrictions can be used to restrict allowed operations (e.g. @readonly, @Capabilities{...},...). User specific restrictions (@requires / @restrict) allow you to restrict data to individual users. These restrictions usually contain predicate privileges, that are defined using a where clauses based on attributes of the currently logged-in user.



@restrict: [ 
{ grant: 'CREATE', to: 'authenticated-user',
where: '$user.country = ''DE''' }
]

For detailed information, you can follow the excellent documentation in the CAP source:




Make sure your service is annotated with @(requires:'authenticated-user')



Example 
service CurrentUserProfileService @(requires: 'authenticated-user') {

Getting Current User in CAP NODEJS


In CAP Node.js, you get the ID of the current user from req.user.id as shown in the example below:



module.exports = srv => {

const { Projects } = srv.entities
srv.before(['CREATE', 'READ', 'UPDATE', 'DELETE'], 'CurrentUserProfile',
(req) => {
const currentLoggedonUser = [
{
id: req.user.id,
email: req.req.authInfo.getEmail(),
username:
req.req.authInfo.getGivenName() +
" " +
req.req.authInfo.getFamilyName(),
roles: roles
},
];

return currentLoggedonUser;
});

}

For a detailed example, you can also refer to the following blog post:





3.4) Getting Current User in CAP JAVA



This section provides valuable insights into obtaining the Current User in CAP Java applications.


The Request Context provides information about the request's parameters as well as the current user:
UserInfo: Exposes an API to fetch data of the (authenticated) user such as the logon name, id, CAP roles, and the tenant.






import cds.gen.Requestservice.CurrentUserContext;
//...
@On(event = "currentUser")
public void currentUser(CurrentUserContext context) {
UserInfo userInfo = context.getUserInfo();
boolean isAuthenticated = userInfo.isAuthenticated();
String uName = uI.getName();
// ...
}

To establish type-safe access, additional attributes may also be accessed via custom extensions of UserInfo. To map XSUAA users, the interface XsuaaUserInfo is available by default. You can create XsuaaUserInfo instances either by calling userInfo.as(XsuaaUserInfo.class) or by Spring injection:




@Autowired
XsuaaUserInfo xsuaaUserInfo;

@Before(event = CqnService.EVENT_READ)
public void beforeRead() {
boolean isAuthenticated = xsuaaUserInfo.isAuthenticated();
String email = xsuaaUserInfo.getEmail();
String givenName = xsuaaUserInfo.getGivenName();
// ...
}

 

For more details, please follow the instructions in the






3.5) Getting Current User for APPRouter, SAPUI5, and NodeJS Application Types


In this section, I will guide you on how to access the Current Logged-on User Details for different application types, such as APPRouter, SAPUI5, and NodeJS.


Within the SAP Business Technology Platform (BTP) NEO environment, there exists a service known as the User API service, enabling you to fetch information about the currently logged-in user.

For more details on using the User API service in your BTP NEO HTML5 application, please refer to the help document: https://help.sap.com/docs/btp/sap-btp-neo-environment/accessing-user-api.

To enable this functionality, add a route to your neo-app.json application descriptor file.

Moreover, on BTP Cloud Foundry (CF), you can also leverage the User API service within your HTML5 and SAPUI5 applications, as well as Approuter. The advantage here is that you won't need an explicit backend OData service call.

This User API service supports the following endpoints:

  • /currentUser

  • /attributes


To integrate this into your application, simply add a route to your xs-app.json application descriptor file as shown below:

The following example handles only the /currentUser endpoint:


 {
"source": "^/user-api/currentUser$",
"target": "/currentUser",
"service": "sap-approuter-userapi"
}


The following example handles both endpoints [/currentUser & /attributes ]


{
"csrfProtection": false,
"source": "^/user-api(.*)",
"target": "$1",
"service": "sap-approuter-userapi",
"authenticationType": "xsuaa"
}



Then call end point either from UI5 or jQuery Ajax Calls
//Sample code
$.ajax({

"url": "/userapi/currentUser",
async: false,
success: jQuery.proxy(function (user) {

var currentUser = {
fullName: user.lastName + ", " + user.firstName,
userId: user.name,
};
//Here you can also set object to your oData Model

...

});
}

For more information and detailed implementation, you can refer to the following resources:




The User API service provides an API to query the details of the user that is currently logged on to the HTML5 application. The retrieved user details may include:



{
"firstname": "John",
"lastname": "Doe",
"email": "john.doe@sap.com",
"name": "john.doe@sap.com",
"displayName": "John Doe (john.doe@sap.com)", (The user ID in the identity provider),
"scopes": ["openid","user_attributes","uaa.user"] (Only if the authentication type is “xsuaa")
}

With this information, you can efficiently manage user authentication and tailor the user experience in your applications.






Request for Feedback and Support:


Thanks for reading! If you found this post helpful, please consider ‘'Like' ,'Share' it with your network. Your support helps me create more valuable content. I welcome any feedback or suggestions - feel free to comment . Don't forget to 'Follow' me for more content like this.
Your support means a lot to me!

About me :


LinkedIn > Showkath


2 Comments