Skip to Content
Technical Articles
Author's profile photo Philipp Herzig

Step 7 with SAP Cloud SDK: Secure your Application on SAP Cloud Platform, CloudFoundry

Disclaimer:

This blog post is only applicable for the latest version 2 of the SAP Cloud SDK. You can find an updated tutorial for version 3 over at our tutorial page.

The following steps will explain how to secure applications in SAP Cloud Platform, CloudFoundry which are built based on the SAP Cloud SDK.

Note: This post is part of a series. For a complete overview visit the SAP Cloud SDK Overview.

Goal of this blog post

This tutorial will cover how to protect your Java-based Hello World microservice with authenticated and authorized users. To achieve this the tutorial covers the following aspects:

  1. Setting up and configuring the App Router component as a central entry point to your microservice landscape to handle authentication and authorization for you.
  2. Protect your Java microservice so that it only accepts requests based on a valid JSON Web Token (JWT) that is received from the App Router.
  3. Assign roles and scopes to your application users and let your backend deal with authorization information.

Prerequisites

  • You did at least all steps until Step 3 with SAP Cloud SDK: HelloWorld on SCP CloudFoundry.
  • If you created already a Cloud Foundry Trial account in the past, please verify that the global account is not a standalone (account created before Mai 2017) as we have at the moment a small bug with standalone accounts. We are working on it and I will update the blog as soon as this is perfectly working. In the meantime, I would suggest you to create a new Trial Account if you want to test it now (cf. https://blogs.sap.com/2017/07/09/how-to-use-the-sap-cloud-platform-connectivity-and-the-cloud-connector-in-the-cloud-foundry-environment-part-1/).
  • To make the examples a bit more plastic, I created a completely new trial using a P-User with a throw-away e-mail address.

Concepts

Before we dive deeper into the real setup of the architecture, let’s quickly review the architecture we intend to go for.

Figure 1 presents the final setup. First, we still have our existing “Hello World” or “Business Partner” Java-based microservice that we have created in the previous tutorials. However, instead of letting the customer access this application directly, we will use the so-called Application Router (App Router) that serves two purposes.

On the one hand, the App Router is a general entry point into the world of microservices. The main idea is that you can split an application into multiple microservices with independent deployability, polyglot runtimes & persistence and independent teams. Therefore, a central entry component is required that hides the complexity of the microservice landscape from the end customer.

On the other hand, the App Router is mainly responsible for managing authentication flows. The App Router takes incoming, unauthenticated requests from users and initiates an OAuth2 flow with the XSUAA service. The XSUAA service is an SAP-specific fork of CloudFoundry’s UAA service to deal with authentication and authorization (it may again delegate this aspect to other providers such as external Identity Providers, see later in this tutorial). If the user authenticates at the XSUAA, it will respond with a JSON Web Token (JWT) containing the authenticated users as well as all scopes that he or she has been granted.

Figure 1: Authentication Flow during Runtime

The JWT is passed by the App Router to the underlying microservices so that they are freed up from this task. At the same time, these microservices can only be accessed with a valid JWT, hence, are protected from unauthenticated traffic.

The JWT contains a signature that needs to be verifiable by every microservice to establish trust. Hence, every service require a key (client-secrets or public keys) to verify this signature and reject any requests with non-valid JWTs. Therefore, every service has to maintain a service binding to the XSUAA that provides this information for runtime verification (Figure 2). To enable this, every microservice binds to a dedicated XSUAA instance which writes this information into the VCAP_SERVICES environment variable which the microservices can use to verify any token’s validity.

Figure 2: Provisioning view with XSUAA binding

 

With these basics in mind, let’s create the picture of Figure 1 and Figure 2 by setting up the App Router, XSUAA and backend microservices to enable full application security.

Setup the App Router to authenticate your users.

We will let Cloud Foundry retrieve the App Router automatically on deployment. To achieve this, we will first setup the necessary structure.

  1. Go to your favourite <destLocation> and create the approuter directory
    cd <destLocation>
    mkdir approuter
    cd approuter
  2. Place the following package.json in your approuter directory
    {
      "name": "approuter",
      "dependencies": {
        "@sap/approuter": "*"
      },
      "scripts": {
        "start": "node node_modules/@sap/approuter/approuter.js"
      }
    }
  3. Within <destLocation>/approuter create a new file called xs-app.json with the following content:
    {
      "welcomeFile": "index.html",
      "routes": [{
        "source": "/",
        "target": "/",
        "destination": "app-destination"
      }]
    }
  4. Last but not least create a new manifest.yml file within <destLocation> for the AppRouter microservice with the following content:
    ---
    applications:
    - name: approuter
      routes:
        - route: approuter-<subdomain>.cfapps.&lt;region_id&gt;.hana.ondemand.com
      path: approuter
      memory: 128M
      buildpacks:
        - nodejs_buildpack
      env:
        TENANT_HOST_PATTERN: 'approuter-(.*).cfapps.<region_id>.hana.ondemand.com'
        destinations: '[{"name":"app-destination", "url" :<APPLICATION_URL>, "forwardAuthToken": true}]'
      services:
        - my-xsuaa

    Adapt the file as follows:

    • Replace <subdomain> with your subdomain. You will find your subdomain in the CF cockpit by heading to the overview page of your sub-account:

       

      • Swap out both instances of <region_id> with your specific region (e.g. eu10). You can find it for instance included in the API endpoint (also listed in the image above) just before hana.ondemand.com. More details on the region specific URLs can be found here.
      • In destinations replace <APPLICATION_URL> with the actual URL of your previously deployed app. Again you can find it in the CF cockpit or by listing all existing routes via routes.

      Understanding the AppRouter’s manifest.yml and xs-app.json:

      On Cloud Foundry every sub-account is assigned exactly one subdomain which is associated to exactly one tenant. In a multi-tenant scenario the app router needs to know which tenant to forward to the XSUAA service. This is achieved by including the subdomain in the host, from which the app router will extract it. That is where the TENANT_HOST_PATTER comes into play. It is a variable that declares the pattern how tenants in the URL are identified and handled. For this tutorial we expect the host to conform to approuter-<subdomain>. If you desire different URL patterns, you need to change the route and TENANT_HOST_PATTERN accordingly.

      Note that the TENANT_HOST_PATTER variable is only required in real multi-tenant application, i.e, applications where a physical deployment serves multiple clients from the same deployment. We assume in this tutorial series that we want to build multi-tenant applications, as we aim towards cloud-native development. However, this variable is not necessary if you have a single-tenant application. To realize this, the xs-security.json security descriptor may declare “tenant-mode”: “dedicated” (see step 5 below).

      Moving on to the destinations entry. It is a variable that declares the internal routes from the App Router to the underlying backend microservices. As we only have one microservice yet, we define only one destination called app-destination here. This app-destination is referenced by the previously created xs-app.json file.

      Last but not least the services section declares to bind our own XSUAA service instance to the App Router. This binding will ensure a corresponding VCAP_SERVICES entry that holds the client ID, client secret and public key that is required to validate any incoming OAuth token/JWT from the XSUAA service:

      <img />

      Bind the XSUAA Service

      Now we need to create a service binding to the XSUAA service. As a prerequisite we require a xs-security.json (security descriptor) file that contains a declaration about authorization scopes we intend to use in our application. In our case, we simply declare a DISPLAY scope that we will use later on to authorize our users. In addition, we declare a so-called role template called “Viewer” that references our DISPLAY scope. We put this file to <destLocation>/xs-security.json. For a more detailed explanation on scopes and role templates, see the appendix of this tutorial. More details on the syntax of the xs-security.json can be found here.
      Note 1: that the xsappname has to be unique within the entire XSUAA instance. We follow here the same pattern using our <app-name>-<subdomain>.
      Note 2: As explained above: tenant-mode: shared assumes a multi-tenant application and will require the TENANT_HOST_PATTERN variable to be declared. You may also use “tenant-mode”: “dedicated” if you develop a single-tenant application.

      {
        "xsappname": "firstapp-<subdomain>",
        "tenant-mode": "shared",
        "scopes": [
          {
            "name": "$XSAPPNAME.Display",
            "description": "display"
          }
        ],
        "role-templates": [
          {
            "name": "Viewer",
            "description": "Required to view things in our solution",
            "scope-references"     : [
              "$XSAPPNAME.Display"
            ]
          }
        ]
      }

      Create the file and change the app name just like before.

      We then create a service instance called my-xsuaa of the XSUAA service by issuing the following command and using the xs-security.json file:

      cf create-service xsuaa application my-xsuaa -c xs-security.json

      If you have created this instance of the XSUAA service before without the xs-security.json parameter, you can unbind and delete the existing instance with these commands before creating it with the above command:

      cf unbind-service firstapp my-xsuaa
      cf delete-service my-xsuaa​

      After you have created the XSUAA service instance, deploy the app router using the following (with the appropriate API endpoint of your Cloud Foundry region):

      cd <destLocation>
      cf api https://api.cf.eu10.hana.ondemand.com
      cf login
      cf push

      Afterwards you should be able to locate the App Router from within your browser using the host name of your deployment, which should face you with the following login page where you can use your user e-mail and password:



      After logging in you should see the HelloWorld servlet which is now served by the App Router as a proxy to your Java application:

      Protect your backend microservice

      After authentication works with the App Router, your java backend service is still fully visible in the web and not protected. We, therefore, need to protect our java microservices as well so that they accept requests with valid JWTs for the current user only. In addition, we will setup the microservice in a way that it deals with authorization, i.e., understands the OAuth scopes from the JWT that we have configured previously using the xs-security.json file.

      In the following, we will use the Spring Security framework to protect the microservices. You can also use standard mechanisms of the SAP Java buildpack to achieve the same. If you do not want to use Spring Security please follow the steps here, nonetheless, the concepts described hereinafter apply for both methods.

      Install XS Security libs to your local Maven repository:

      The first step is to get some additional Java libs from Service Marketplace. To get them, do the following steps:

      1. Download additional XS security libs from service marketplace:https://launchpad.support.sap.com/#/softwarecenter/search/XS_JAVA
      2. At the time of writing the latest package is XS_JAVA_4-70001362.ZIP.
      3. Unzip <destLocation>
      4. Install XS Security Libs to your local maven repo using:
        cd <destLocation>
        mvn clean install

      Enhance your project’s pom.xml

      In the second step, we go back to our HelloWorld or Business Partner application and open the main application/pom.xml which looks similar to this structure:

      In the <dependencies> section of the application/pom.xml, we enhance the following additional dependencies to our project:

      <!-- Authentication and Authorization imports with Spring Security -->
      <dependency>
          <groupId>com.sap.xs2.security</groupId>
          <artifactId>security-commons</artifactId>
          <version>0.28.6</version>
      </dependency>
      <dependency>
          <groupId>com.sap.xs2.security</groupId>
          <artifactId>java-container-security</artifactId>
          <version>0.28.6</version>
      </dependency>
      <dependency>
          <groupId>com.sap.xs2.security</groupId>
          <artifactId>java-container-security-api</artifactId>
          <version>0.28.6</version>
      </dependency>
      <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-jwt</artifactId>
          <version>1.0.9.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>org.springframework.security.oauth</groupId>
          <artifactId>spring-security-oauth2</artifactId>
          <version>2.2.3.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>com.sap.cloud.security.xsuaa</groupId>
          <artifactId>api</artifactId>
          <version>1.6.0</version>
      </dependency>
      <dependency>
          <groupId>com.sap.security.nw.sso.linuxx86_64.opt</groupId>
          <artifactId>sapjwt.linuxx86_64</artifactId>
          <version>1.1.19</version>
      </dependency>
      

      This dependency section contains three main parts of dependencies:

      1. The org.springframework.security packages add certain aspects of the Spring security framework to our application, in particular the OAuth framework of Spring security.
      2. The com.sap.xs2.security packages contain specific security adaptations for the CloudFoundry environment.
      3. The com.sap.security packages contain platform-specific native implementations for the JWT validation and support OAuth2 authentication.

      Add Spring as Servlet Listener to your web.xml

      Afterwards you need to go to your web.xml in src/main/webapp/WEB-INF and add the following lines. If you have used the Archetype in Step 3 of the Tutorial: https://blogs.sap.com/2017/05/19/step-3-with-sap-s4hana-cloud-sdk-helloworld-on-scp-cloudfoundry/ these lines should be already there and you can simply uncomment them.

      <listener>
          <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      <context-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>/WEB-INF/spring-security.xml</param-value>
      </context-param>
      <filter>
          <filter-name>springSecurityFilterChain</filter-name>
          <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
      </filter>
      <filter-mapping>
          <filter-name>springSecurityFilterChain</filter-name>
          <url-pattern>/*</url-pattern>
      </filter-mapping>

      This configuration introduces the Spring Security Filter Chain on all incoming routes of your Java microservice and declares that the entire security configuration can be found in a file called spring-security.xml.

      Introducing spring-security.xml

      In the next step we need to protect our routes on a more fine-grained basis by introducing the file spring-security.xml to our /src/main/webapp/WEB-INF directory. If you have used the Archetype in Step 3 of the Tutorial: https://blogs.sap.com/2017/05/19/step-3-with-sap-s4hana-cloud-sdk-helloworld-on-scp-cloudfoundry/ this file should be already there.

      To protect all your routes so that users have to be at least authenticated you have to uncomment or introduce the following line to spring-security.xml:

      <sec:intercept-url pattern="/**" access="isAuthenticated()" method="GET" />

      This code says that all users which access all URLs under / with the GET method have to be at least authenticated. You can find the full reference for access management here: https://docs.spring.io/spring-security/site/docs/current/reference/html/el-access.html

      The full spring-security.xml should look like this:

      <?xml version="1.0" encoding="UTF-8" ?>
      <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
         xmlns:sec="http://www.springframework.org/schema/security"
       
         xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2
             http://www.springframework.org/schema/security/spring-security-oauth2-1.0.xsd
              http://www.springframework.org/schema/security
              http://www.springframework.org/schema/security/spring-security-3.2.xsd
              http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
       
         <!-- protect secure resource endpoints ================================================ -->
       
         <sec:http pattern="/**" create-session="never"
            entry-point-ref="oauthAuthenticationEntryPoint"
            access-decision-manager-ref="accessDecisionManager"
            authentication-manager-ref="authenticationManager"
            use-expressions="true">
            <sec:anonymous enabled="false" />
       
            <!-- section to protect your endpoints -->
       
            <!-- Example: Check a specific OAuth Scope (i.e., authorization) on a resource -->
            <!--<sec:intercept-url pattern="/hello" access="#oauth2.hasScope('${xs.appname}.Display')" method="GET" />-->
       
            <!-- Example: Check only authentication on a resource -->
            <sec:intercept-url pattern="/**" access="isAuthenticated()" method="GET" />
       
            <sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
            <sec:access-denied-handler ref="oauthAccessDeniedHandler" />
         </sec:http>
       
         <bean id="oauthAuthenticationEntryPoint"
            class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
         </bean>
       
         <bean id="oauthWebExpressionHandler"
            class="org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler">
         </bean>
       
         <bean id="accessDecisionManager"
            class="org.springframework.security.access.vote.UnanimousBased">
            <constructor-arg>
               <list>
                  <bean class="org.springframework.security.web.access.expression.WebExpressionVoter">
                     <property name="expressionHandler" ref="oauthWebExpressionHandler" />
                  </bean>
                  <bean class="org.springframework.security.access.vote.AuthenticatedVoter"  />
               </list>
            </constructor-arg>
         </bean>
       
          <sec:authentication-manager alias="authenticationManager"/>
       
         <oauth:resource-server id="resourceServerFilter"
            resource-id="springsec" token-services-ref="offlineTokenServices" />
       
         <bean id="offlineTokenServices"
               class="com.sap.xs2.security.commons.SAPOfflineTokenServices">
               <property name="verificationKey" value="${xs.uaa.verificationkey}" />
               <property name="trustedClientId" value="${xs.uaa.clientid}" />
               <property name="trustedIdentityZone" value="${xs.uaa.identityzone}" />
          </bean>
       
         <bean id="oauthAccessDeniedHandler"
            class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
       
         <!-- define properties file =========================================================== -->
         <bean class="com.sap.xs2.security.commons.SAPPropertyPlaceholderConfigurer">
            <property name="location"  value="classpath:/application.properties" />
         </bean>
      </beans>

      Modify your backend manifest.yml to bind XSUAA and trust for all identity zones

      Now we need to modify the manifest.yml a bit to interpret the JWT sufficiently. To do this add the following lines to your backend microservice’s manifest.yml file:

      SAP_JWT_TRUST_ACL: '[{"clientid" : "*", "identityzone" : "*"}]'

      In addition, we need to bind our my-xsuaa instance to our java backend service as well so that we have the OAuth secret to validate the JWT’s signature

      services:
      - my-xsuaa

      Deploy and test the application

      Now we are ready to build and deploy the application to try all our changes with

      mvn clean install
      cf push

      After deployment, accessing your backend service should not be possible anymore and will quit with the following message:

      However, you should be still able to access your application using the App Router as the entrypoint:

      Recommended Changes with Usage of AppRouter

      Removed Mocked Auth User

      If you have previously enabled the mocking of tenant and user information via the environment variable ALLOW_MOCKED_AUTH_HEADER as mentioned in Step 5 of this tutorial series, you should now remove this setting. Execute the following command:

      cf unset-env firstapp ALLOW_MOCKED_AUTH_HEADER

      Removed CSRF Token protection from backing service

      If you have previously exposed the backing service directly to the end user, you have used the RestCsrfPreventionFilter on the backend to protect against Cross-Site-Request-Forgery. As this is now in the responsibility of the App Router, we should remove it. For this remove the following lines from your web.xml:

      <filter>
        <filter-name>RestCsrfPreventionFilter</filter-name>
        <filter-class>org.apache.catalina.filters.RestCsrfPreventionFilter</filter-class>
      </filter>
      <filter-mapping>
        <filter-name>RestCsrfPreventionFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>

      Use OAuth scope to authorize users

      Now that we saved the backend microservice from unauthenticated users, we also want to make sure that certain endpoints can be called only when users have specific authorizations. In the following example, we want to use our Display OAuth scope.

      Enhance spring-security.xml to protect routes with OAuth scopes

      The backend itself can be easily adapted based on the spring-security.xml. In this case, we protect the /hello route with our Display OAuth Scope. Introduce (or uncomment) the following line within the <sec:http> element:

      <sec:intercept-url pattern="/hello" access="#oauth2.hasScope('${xs.appname}.Display')" method="GET" />

      Afterwards you need to redeploy the application with

      mvn clean install
      cf push

      Assign users to scopes

      Furthermore, the user accessing the application, needs to be assigned the Display OAuth scope. This is done using the SCP cockpit.

      First, go to your trial account on Cloud Foundry and find the role collections menu under the Security module:

       

      Second, create a new role collection which you can give an arbitrary name. In our case, we call the role collection Business Partner Manager.

       

      Afterwards, select the role collection “Business Partner Manager” and select “Add Role”. From the menu, select your application and the corresponding role template and role as shown below:

       

      Afterwards, the user has to be assigned to the newly created Business Partner Manager in order to receive the Display scope. In order to do this, select the trust configuration from the security menu and select the SAP ID Service from the list:

       

      In the opening dialog, enter your User ID as e-mail into the user field and click “Show Assignments” followed by “Add Assignments”:

       

      Select the “Business Partner Manager” role collection from the menu to assign it to your user:

       

      Afterwards you have a route that is protected by the Display OAuth scope which you can still access because the user has now the corresponding role.

      That’s it for today. Now you have learned the basics to protect your application on SAP Cloud Platform, CloudFoundry based on the SAP Cloud SDK. Stay tuned for upcoming blog posts about more advanced usages of the SAP Cloud SDK.

       

      Appendix

      Understanding Roles, Role Collections and Scopes

      The following picture explains how the various concepts are related to each other.

      Gray Box: As a SCP developer (e.g., SAP, partner, customer) of the business application (gray box), you define role templates which may contain multiple OAuth scopes. The developer here define the scope, role templates and additional attributes within the xs-security.json as explained in this tutorial which is used when creating the service instantiation to the XSUAA.

      Orange Box: As an SCP tenant administrator of the business application (customer) can create a role collection which is spanning multiple roles reflecting the role templates. This way you can achieve, on the one hand, a fine-granular authorization control for the microservices and, on the other hand, compose them very flexibly in coarse-grained role collections. The idea behind this is, that, for example, the Business Partner Manager role collection may span multiple applications and microservices all having individual scopes. The role collections resolves the roles and scopes and returns a union of all scopes which are composed by the role collection.

      Green Box: As an administrator of the users (customer), the role collection can then be assigned to the final user using the SAML attribute “Groups”.

      Troubleshooting Json Web Tokens

      Sometimes it might be necessary to investigate the JWT on the backend microservice during development to check for potential errors. Here is an example Servlet that prints the token out.

       @WebServlet("/debug")
      public class JwtDebugServlet extends HttpServlet {
       
          @Override
          protected void doGet(final HttpServletRequest request, final HttpServletResponse response )
                  throws ServletException, IOException
          {
              response.setContentType("text/plain");
              Enumeration headerNames = request.getHeaderNames();
              while (headerNames.hasMoreElements()) {
                  String key = (String) headerNames.nextElement();
                  String value = request.getHeader(key);
       
                  response.getOutputStream().println(key+" : "+value);
              }
          }
      }

      Afterwards you may use https://jwt.io/ to decode the token. Note: You should never use this with any productive JWT as these tokens are shared on a public website. Fallback to local solutions.

      Troubleshooting OAuth Scopes from XSUAA

      In addition, you may use the XSUAA to see which current scopes and roles a particular users has. You could do this with your XSUAA tenant-specific URL:

      https://<subdomain>.authentication.<region_id>.hana.ondemand.com/config?action=who

      It will return something similar to this:

      Setting up your own Identity Provider

      So far, we have used the XSUAA service itself as the user provider. However, in production scenarios customer’s may want to use their own Identity Provider (IdP) as a user provider or delegate into on-premise user stores such as LDAP or ActiveDirectory. In the following, we quickly show how the XSUAA service can delegate requests to such an external IdPs.

      To make this happen, the IdP and the service provider (SP) have to exchange security metadata, i.e., the IdP has to import the metadata of the SP and vice versa.

      You can retrieve the metadata from your XSUAA tenant by following the pattern https://<subdomain>.authentication.<region_id>.hana.ondemand.com/saml/metadata. This downloads the metatdata to your local computer.

      Second, you need to import the metadata into your IdP. In the following, we use an own SAP Cloud Identity tenant to do this.

      1. Within the IdP, we have to create a new application called MyApp where we select the SAML 2.0 Configuration
      2. Import the SP’s metadata and click “Save”.
      3. Back in the SCP account cockpit we need to add the IdP’s metadata in the same manner
      4. Click “New Trust Configuration” and add the metadata from the IdP and click “Save”

Assigned Tags

      119 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Martijn de Boer
      Martijn de Boer

      Hello Philipp,

       

      Nicely written.

      Some comments:

      1)  TENANT_HOST_PATTERN is a variable required for multi tenant applications. This is the default in the application plan.  If the application is not a multi-tenant aware application, you can add the following entry to your xs-security.json:

      "tenant-mode":"dedicated"

      When adding this and recreating a service instance, it is not required to set the TENANT_HOST_PATTERN .

      2) Many applications use spring for their logic. For applications not using spring, an alternative is to use the sap_java buildpack and set authentication method XSUAA in web.xml See https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/53671c1034d44c83b90b104904d9fb07.html

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Martijn,

      thanks a lot for the feedback, very good points. I tried to incorporate them already during the text now!

      Thanks a lot

      Philipp

      Author's profile photo Wolfgang Janzen
      Wolfgang Janzen

      I also like the summary; it provides a good introduction to the fairly complex topic.

       

      Regarding Appendix: Understanding Roles, Role Collections and Scopes

      It might be worth to emphasize that the different areas (highlighted with different colors) aims at different target groups:

      Green -> IdP User Manager (customer)
      Red   -> SAP Cloud Platform Tenant Admin (customer)
      Grey  -> SAP Cloud Platform Developer (SAP / partner / customer)

      Currently we only support the mapping from IdP User Groups (via SAML attribute "Groups" - the name is currently hard-coded) to Role Collections. The same IdP User Group can be used to assign one or more Role Collection to a user (on UAA side).

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Wolfgang,

      thanks a lot for the feedback. The article now tries to highlight this distinction better.

      Thank you

      Philipp

      Author's profile photo Sander Wozniak
      Sander Wozniak

      Here is an example of the “Groups” attribute that is required for mapping SAML groups to Role Collections:

       

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Update History

      • 06.10.2017: Changes XS2 security libs to LATEST version to avoid troubles with newer versions of these libs as they are not managed over Maven Central.
      • 18.09.2017: Recommendations after usage of App Router (e.g., mocked auth user, CSRF Filter)
      • 12.08.2017: Updated to Spring Security OAuth 2.2.0-RELEASE dependency: http://spring.io/blog/2017/07/28/spring-security-oauth-2-2-released
      • 24.03.2018: Updated Java dependencies to latest XS2 security libs (0.27.2) and OAuth 2.3.2.RELEASE
      • 04.10.2019: Updated Java dependencies to latest XS2 security libs (0.28.6) and OAuth 2.3.3.RELEASE. 
      • 04.10.2019: Removed spring-core dependency as it was a constant point of confusion as spring-core is delivered transitively by org.springframework.security.oauth
      Author's profile photo Former Member
      Former Member

      Hi Philipp,

      Thanks for posting the blog. When i run the command

      cf api https://api.cf.us10.hana.ondemand.com

      It raises the following exception. Can you please help in resolving the same?

      Exception 0xc0000005 0x0 0x42024dbf 0x7ffdcf080e57
      PC=0x7ffdcf080e57

      Thanks,

      Sankeerth

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hello Sankeerth,

      this sounds like a very general issue with your cf command line client. Can you post what cf help brings up?

      Thank you

      Philipp

      Author's profile photo Former Member
      Former Member

      Hi Philipp,

      Thanks for the response. Below is the result of cf help.

      C:\Users\sankeerth\workspace\cf_firstapp>cf help
      Warning: Error read/writing config: unexpected end of JSON input for C:\Users\sankeerth\.cf\config.json
      cf version 6.32.0+0191c33d9.2017-09-26, Cloud Foundry command line tool
      Usage: cf [global options] command [arguments...] [command options]
      
      Before getting started:
      config login,l target,t
      help,h logout,lo
      
      Application lifecycle:
      apps,a run-task,rt events
      push,p logs set-env,se
      start,st ssh create-app-manifest
      stop,sp app
      restart,rs env,e
      restage,rg scale
      
      Services integration:
      marketplace,m create-user-provided-service,cups
      services,s update-user-provided-service,uups
      create-service,cs create-service-key,csk
      update-service delete-service-key,dsk
      delete-service,ds service-keys,sk
      service service-key
      bind-service,bs bind-route-service,brs
      unbind-service,us unbind-route-service,urs
      
      Route and domain management:
      routes,r delete-route create-domain
      domains map-route
      create-route unmap-route
      
      Space management:
      spaces create-space set-space-role
      space-users delete-space unset-space-role
      
      Org management:
      orgs,o set-org-role
      org-users unset-org-role
      
      CLI plugin management:
      plugins add-plugin-repo repo-plugins
      install-plugin list-plugin-repos
      
      Commands offered by installed plugins:
      
      Global options:
      --help, -h Show help
      -v Print API request diagnostics to stdout
      
                    
      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      I did not have this error before, but your cf config.json seems to be broken. Maybe reinstalling the CF CLI tools help. Is the exception address the only thing that appears on cf api?

      Author's profile photo Former Member
      Former Member

      I tried a couple of solutions but none of those helped in solving this issue.

      1. Deleted config.json file and let CF generate that again.
      2. Reinstalled the CF CLI tool.

       

       

      Author's profile photo Former Member
      Former Member

      This exception also occurring when I use the commands cf login.

       

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Sankeerth,

      unfortunately, I cannot help you here as this seems to be a CF CLI related issue. Please try to ask your question on Stackoverflow: https://stackoverflow.com/questions/tagged/cloudfoundry

      Best regards

      Philipp

      Author's profile photo Nick van Heertum
      Nick van Heertum

      I followed your guide and tried to switch to our own IdP.

      When I launch my app it asks to login but it is not my IdP but the iot-security (https://iot-security.accounts.ondemand.com/) one.

       

      Any ideas?

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Nick,

      hard to say without having more details and not having any information on your SP. Have you really imported the metadata from whatever subaccount (provider, consumer) into your own IdP and also vice versa, i.e., your IdP has the metadata of your whatever XSUAA instance that is attached to your SP.

      If you have logged in before, you may also require to kill any existing session cookies using Chrome Dev Tools or similar.

      I could have a look, if you give me more details or even access to your account.

      Best

      Philipp

      Author's profile photo Former Member
      Former Member

      Hi Philipp,

      This is one of the blog which has covered all the topics needed to enable and handle security. Thanks for such a great content. Really appreciate your effort.

      Keep on posting.

      Best Regards, Kirti Kumar Sharma

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Kirti,

      happy that the blog helped you and hope you enjoy working with SAP Cloud Platform and CloudFoundry.

      Best regards

      Philipp

      Author's profile photo SIMMACO FERRIERO
      SIMMACO FERRIERO

      Hi Philipp,

      I’ve a question for you :

      I’ve followed your blog with my SAP Cloud Foundry Trial Landscape account and all worked fine.

      Now I’ve created a new account on the Trial Landscape environment, it’s just a test account.

      However, when I try to run the phase where the user has to assign a role collection to his trust configuration I get the following error:

      Does this means that only “real” SAP accounts can follow your blog? Is there any easy way to fix it? I tried also with the P-Number, but I got the same results.

      Regards,

      Simmaco

       

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Simmaco,

      thanks for your feedback. This error typically occurs, if you haven't logged in with this specific user at your XSUAA instance before (e.g., on approuter). After logging in once, you should be able to edit assignments for your user.

      Best regards

      Philipp

      Author's profile photo SIMMACO FERRIERO
      SIMMACO FERRIERO

      Hi Philipp,

      it seems that the link for downloading the "XS_JAVA" package now brings to an empty list. Could you please double check? I had to type "XS_JAVA" in the search box for downloading the package.

      Thanks,

      Simmaco

       

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Fixed. Thanks for the remark.

      Author's profile photo Bert Deterd
      Bert Deterd

       

      @SAP/approuter cannot be found by CF

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Bert,

      seems like you have pushed only the package.json to CF and CF does not have a link to the SAP NPM registry. I would recommend set the config + npm install locally and then push the whole local content to CF. Maybe it works with an extra .npmrc file (https://github.com/npm/npm/issues/4145), but I have never tried this myself.

      Best regards

      Philipp

       

      Author's profile photo Henning Heitkoetter
      Henning Heitkoetter

      Change log (January 4, 2018):

      • Adapt to new business partner example
      • Change XSUAA service instance name to my-xsuaa (instead of myuaa) and other changes to maintain consistency troughout the tutorial
      Author's profile photo Bruno Mihailescu
      Bruno Mihailescu

      Very good article. I only have one question. From the JWT Token I can get only the scope of the current logged on user. Is there a way to see also the roles behind that scope using xs2 security ?

      Thank you,

      Bruno.

       

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Bruno,

      not to my knowledge, I also just but it is an interesting question. I will check this soon when I will touch this topic again. Also the XS2 libraries do not seem to have any methods for retrieving the roles from the JWT.

      Best regards

      Philipp

       

      Author's profile photo Joice Liu
      Joice Liu

      Thanks Philipp. You post has helped me a lot in securing my XSA application which currently I have been working on recently.

      I faced the issue having access problem in through web router to the application, from your post I realized, I didn't forward the Token currently through destination in the manifest.yml when I push the application.

      In terms of this URL cfapps.eu10.hana.ondemand.com you used in the destination as well as api setup. Currently, I can only use URL which is the machine host with expected port where I run this XSA application. I cannot modify this URL like something similar to cfapps.sap.hana.ondemand.com.

      Did I miss something here? Or if it's still unclear, I would like to provide more information I have here.

      Thanks, again!

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Joice,

      happy that the blog helped you to get your security setup fixed.

      Regarding the domain eu10.hana.ondemand.com, you cannot change that at the moment. This is a so-called shared-domain, i.e., an domain that exists across or independent your Cloud Foundry organization. If you try to create your own shared domain using cf create-shared-domain this will return with an error telling you that you are not allowed to create your own shared domain. You can create your own org-specific domains. However, they are not reachable externally.

      Per SCP landscape, there is one dedicated shared domain depending on the datacenter you are in. For the CloudFoundry environment of SAP Cloud Platform you currently have

      • Europe (Frankfurt) with cfapps.eu10.hana.ondemand.com (API endpoint: https://api.cf.eu10.hana.ondemand.com)
      • US East (VA) with cfapps.us10.hana.ondemand.com (API endpoint: https://api.cf.us10.hana.ondemand.com)
      • US Central (Beta) with cfapps.us30.hana.ondemand.com (API endpoint: https://api.cf.us30.hana.ondemand.com)
      • US West (Beta) withcfapps.us20.hana.ondemand.com (API endpoint: https://api.cf.eu10.hana.ondemand.com)

      Best regards

      Philipp

      Author's profile photo Joice Liu
      Joice Liu

      Thanks so much again, Philipp. I will give it a try. 🙂

      Author's profile photo Former Member
      Former Member

      After I deployed the approuter to cloud foundry, the app is getting crashed. Below is the log

       

      2018-04-11T15:26:11.61-0400 [APP/PROC/WEB/0] ERR npm ERR! Linux 4.4.0-111-generic
      2018-04-11T15:26:11.61-0400 [APP/PROC/WEB/0] ERR npm ERR! argv "/home/vcap/deps/0/node/bin/node" "/home/vcap/deps/0/bin/npm" "start"
      2018-04-11T15:26:11.61-0400 [APP/PROC/WEB/0] ERR npm ERR! node v6.13.1
      2018-04-11T15:26:11.61-0400 [APP/PROC/WEB/0] ERR npm ERR! npm v3.10.10
      2018-04-11T15:26:11.61-0400 [APP/PROC/WEB/0] ERR npm ERR! path /home/vcap/app/package.json
      2018-04-11T15:26:11.61-0400 [APP/PROC/WEB/0] ERR npm ERR! code ENOENT
      2018-04-11T15:26:11.61-0400 [APP/PROC/WEB/0] ERR npm ERR! errno -2
      2018-04-11T15:26:11.61-0400 [APP/PROC/WEB/0] ERR npm ERR! syscall open
      2018-04-11T15:26:11.62-0400 [APP/PROC/WEB/0] ERR npm ERR! enoent ENOENT: no such file or directory, open '/home/vcap/app/package.json'
      2018-04-11T15:26:11.62-0400 [APP/PROC/WEB/0] ERR npm ERR! enoent ENOENT: no such file or directory, open '/home/vcap/app/package.json'
      2018-04-11T15:26:11.62-0400 [APP/PROC/WEB/0] ERR npm ERR! enoent This is most likely not a problem with npm itself
      2018-04-11T15:26:11.62-0400 [APP/PROC/WEB/0] ERR npm ERR! enoent and is related to npm not being able to find a file.
      2018-04-11T15:26:11.62-0400 [APP/PROC/WEB/0] ERR npm ERR! enoent
      2018-04-11T15:26:11.62-0400 [APP/PROC/WEB/0] ERR npm ERR! Please include the following file with any support request:
      2018-04-11T15:26:11.62-0400 [APP/PROC/WEB/0] ERR npm ERR! /home/vcap/app/npm-debug.log

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Sankeerth,

      this looks like the package.json is not deployed to CloudFoundry. Please show the content of your approuter directory and how you push the approuter to CF.

      Thanks

      Philipp

      Author's profile photo Former Member
      Former Member

      I am unable to attached a image here, so writing the folder structure.

      I have following folders and files in approuter.

      • doc folder
      • lib folder
      • node_modules folder
      • approuter.js
      • changelog.md
      • package.json
      • readme.md
      • xs-app.json

      I placed this approuter folder inside a directory(favorite location) along with manifest.yml and xs-security.json files.

       

      In command prompt, i changed the working directory to  favorite location and executed the cf push command.

      Thanks,

      Sankeerth

       

       

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Just to be complete here. This discussion is under investigation in https://stackoverflow.com/questions/49879999/after-deploying-the-approuter-to-cloud-foundry-the-app-is-getting-crashed.

      Author's profile photo Sankalp Rangare
      Sankalp Rangare

      Hi,

      We are not using Java spring framework.

      We have tried steps given in "Configure Integrated Container Authentication of the SAP Java Buildpack".

      But still our app is not protected. Anything we are missing?

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Sankalp,

      using the Spring security artifacts should be independent of whether you are using the rest of the Spring framework or not. Our tutorial series is based on TomEE, hence, the blog is also compatible with non-Spring containers. However, if you need help regarding servlet protection with the standard servlet approach, I need more information on what you did already.

      Btw: The standard servlet approach is also described in our book which will be available at the end of the week: https://www.sap-press.com/extending-sap-s4hana_4655/ .

      In case you want to share your code examples, feel also free to submit your question on StackOverflow: https://stackoverflow.com/questions/tagged/s4sdk

      Thanks

      Philipp

      Author's profile photo Sujith Prathap
      Sujith Prathap

      Hello,

      When I try securing the backend service using spring (Protect your backend microservice).

      I get the following error.

      2018-05-24T16:54:07.54+0530 [APP/PROC/WEB/0] OUT Exit status 0

         2018-05-24T16:54:07.54+0530 [CELL/0] OUT Cell c18a646f-cf40-4970-ab84-836eb4542ce4 stopping instance d50bb138-d189-4b02-66b7-96a5

         2018-05-24T16:54:07.54+0530 [CELL/0] OUT Cell c18a646f-cf40-4970-ab84-836eb4542ce4 destroying container for instance d50bb138-d189-4b02-66b7-96a5

         2018-05-24T16:54:07.57+0530 [API/0] OUT Process has crashed with type: "web"

         2018-05-24T16:54:07.59+0530 [API/0] OUT App instance exited with guid 46be197c-299f-4e0a-a3f4-2c53ebb88333 payload: {"instance"=>"d50bb138-d189-4b02-66b7-96a5", "index"=>0, "reason"=>"CRASHED", "exit_description"=>"Codependent step exited", "crash_count"=>6, "crash_timestamp"=>1527161047538206124, "version"=>"4465e843-c95f-4c61-90f5-a02f3634e563"}

         2018-05-24T16:54:07.80+0530 [CELL/0] OUT Cell c18a646f-cf40-4970-ab84-836eb4542ce4 successfully destroyed container for instance d50bb138-d189-4b02-66b7-96a5

      Best Regards,

      Sujith

      The complete log is available here: https://sap-my.sharepoint.com/:t:/p/s_prathap/ETV0u2xTcrJBru1BWEsAmTIBdu9x_7vzITYLUV8UV6KMOg?e=huE0Gq

       

      Author's profile photo Daniel Kurzynski
      Daniel Kurzynski

      The logs show the following exception:
      java.lang.ClassNotFoundException: org.springframework.web.filter.DelegatingFilterProxy

      Could you please check that you included all the dependencies as shown above.

      Author's profile photo PS GOSWAMI
      PS GOSWAMI

      Hello Phillip,

      We are developing the approuter solution in one of our application in SAP Cloud Foundry.

      There we have successfully implemented the approuter with trust management in CF.

      Now through approuter endpoint URL we are able to navigate to the third party SSO/IdP provider login page and thereafter we are getting the specific user ID back in the approuter (login-provider.js) when SSO has been authenticated against the credentials and back to approuter.

      Now we need to carry forward the same user ID in our actual UI application which we have developed in SAP UI5 for session management and other backend service call (build on nodejs).

      It would be a great help, if you can show us some path to do the same.

       

      Regards,

      Partha

      Author's profile photo Dennis Hempfing
      Dennis Hempfing

      Hi Partha,

      thank you for your question! Have you verified whether your XSUAA instance returns a JWT in the HTTP header? If so, you should be able to read the user ID from there.

      I hope this helps you! If not, don't hesitate to ask further questions.

      Best regards,

      Dennis

      Author's profile photo PS GOSWAMI
      PS GOSWAMI

      Hi Dennis,

      I'm getting the JWT token in login-provider.js in approuter and getting the userid there.

       

      Now struggling to carry forward the userid to the destination application (SAP UI5).

      Could you please help to to find the path forward that how I can get the same userid in SAP UI5 application. This will be a great help! Thank you.

       

      Regards,

      Partha

      Author's profile photo Dennis Hempfing
      Dennis Hempfing

      Hi Partha,

      as far as I am aware, when redirecting incoming request (based on the "routes" in the xs-app.json), the approuter should by default forward the JWT to the respective destination.

      Are you using the approuter as-is or have you done any modifications to it?

      Best regards,

      Dennis

      Author's profile photo Nena Raab
      Nena Raab

      Exactly.

      In order to achieve that, you need to connect a dedicated SAML Provider, which supports Single Sign On for Users.

      Please note that you disable the SAP Identity Service in that setup.

      Best regards,

      Nena

      Author's profile photo Nic Botha
      Nic Botha

      Hi Phillip,

       

      thanks for this great blog and also to everyone contributing to the series.

       

      Question - My understanding is that this blog covers the OAuth SAML bearer flow. Now let's assume I want to access the API via POSTMAN using OAuth. How would I go about doing it?

       

      Regards,

      Nic

      Author's profile photo Dennis Hempfing
      Dennis Hempfing

      Hi Nic,

      thank you for your question! I’ve never tried setting this up before, so I cannot give you a definitive answer. However, quick research suggests that Postman seems to support an OAuth setup. Therefore, with a little research, you should be able to set it up.

      Let me know if this helps you and don’t hesitate to come back to us with further questions!

      Best regards

      Dennis

       

      Author's profile photo bernardo ferreira
      bernardo ferreira

      Hi Nic,

      To access via postman you can get the access token through oAuth 2.0 request you will need to send the client id and the client secret.The url for the request will be something like this https://<tenantId>.authentication.eu10.hana.ondemand.com/oauth/token

      Hope you find this useful.

       

      Regards,

      Bernardo Ferreira

      Author's profile photo Nic Botha
      Nic Botha

      Thanks. I've done some reading and would like to share what I've learned. Maybe someone else might find it useful.

      Regards,

      Nic

       

      Author's profile photo Former Member
      Former Member

      Hi Nic,

      I am trying to add this security to my spring-securtiy.xml file. and then when I try to test it via postman by requesting token, it gives me the error of access denied. but if I remove authority code, everything works fine from the postman.

      Can you help me here?

      Thanks,

      Jalpa

      Author's profile photo Guoquan Xing
      Guoquan Xing

      Once uncomment below blocks in firstapp/application/src/main/webapp/web-inf/web.xml

          <listener>
              <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
          </listener>
          <context-param>
              <param-name>contextConfigLocation</param-name>
              <param-value>/WEB-INF/spring-security.xml</param-value>
          </context-param>
          <filter>
              <filter-name>springSecurityFilterChain</filter-name>
              <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
          </filter>
          <filter-mapping>
              <filter-name>springSecurityFilterChain</filter-name>
              <url-pattern>/*</url-pattern>
          </filter-mapping>

      It fails to deploy the app to CF with below log":

       

      java.lang.NoClassDefFoundError: Lorg/springframework/beans/factory/access/BeanFactoryReference;
      Do you have any hints?
      Author's profile photo Christoph Schubert
      Christoph Schubert

      Hi Guoquan,

      thank you for your question! It seems that a new version of the sap-java-buildpack requires a newer version of the spring-core dependency. If you update the version of spring-core from 4.3.0.RELEASE (as described in the blog post) to 5.0.8.RELEASE you should not get any NoClassDefFoundErrors any more.

      If this doesn’t solve your issue don’t hesitate to get back to us!

      Greetings

      Chris

      Edit: I found out that removing the spring-core dependency also works with the latest sdk version, as our SDK bom provided the spring-core dependency in version 5.0.8 out of the box.

      Author's profile photo Guoquan Xing
      Guoquan Xing

      yes, the issue is resolved after I specify the spring-core to a new release, thanks Chris.

      Author's profile photo Frank Chen
      Frank Chen

      Hi Phillip,

      Thanks a lot for your great article! It helps a lot with my current project on cloudfoundry.

      I have one question to take it one step further though. In step 9, we are redirected to the page to login with email and credential. Is there a way for an SAP employee who has the certificate for SSO in the client end to be logged in automatically?

      Thanks again!

      Author's profile photo Dennis Hempfing
      Dennis Hempfing

      Hi Frank,

      thank you for your question! Unfortunately, we have not yet looked into this possibility, so I cannot give you a definitive answer here. Generally, it seems to be possible to configure SSO for your application, see here. However, in order for SAP certificates to be recognized, I'm guessing the respective identity provider would need to be able to validate them.

      Hope this helps you somewhat. Don't hesitate to get back to us if you have further questions!

      Best regards

      Dennis

      Author's profile photo Sankalp Rangare
      Sankalp Rangare

      Link "follow the steps here" in Protect your backend service is not working.

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Yes, thanks for the hint. Not sure it's loading forever for me. However, I cannot find this information on help.sap.com. However, I described the alternative in the book "Extending S/4HANA", Chapter 5 which you can checkout for free here: https://s3-eu-west-1.amazonaws.com/gxmedia.galileo-press.de/leseproben/4655/reading_sample_sappress_1715_ExtendingSAPS4HANA.pdf

      Author's profile photo Dama Ramesh
      Dama Ramesh

       

      Unable to add these dependencies,

      Missing artifact com.sap.xs2.security:security-commons:jar:0.28.6

      Missing artifact com.sap.xs2.security:java-container-security:jar:0.28.6

      Missing artifact com.sap.xs2.security:java-container-security-api:jar:0.27.2

      Missing artifact com.sap.security.nw.sso.linuxx86_64.opt:sapjwt.linuxx86_64:jar:1.0.19

       

      group id “com.sap.xs2.security” not available in Maven repository.

      if any alternate dependencies, send to us.

      Thanks.

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Dama

      please download the libraries from Service Marketplace and install them into your local repository as written in the blog.

      Thanks

      Philipp

      Author's profile photo Dama Ramesh
      Dama Ramesh

      Thank you, I am able to login with sample application.

      Author's profile photo Monish Maharshi
      Monish Maharshi

      Hi Philipp,

       

      I am trying to secure my application with spring security.  I have changed my backend manifest.yml to bind XSUAA and trust for all identity zones. After deployment my backend application and App router are giving the same error as below.

      Also, as recommended by you I have Removed Mocked Auth User but no luck

      Please help me in this regard.

       

      Thank you,

      Monish

       

       

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      This typically indicated an issue with dependencies in your project. Please provide detailed logs on Stackoverflow to investigate the issue further: https://stackoverflow.com/questions/tagged/s4sdk. Please note that I have updated dependencies to the latest and greatest today and tried it successfully out. In addition, I advise you to scan the existing question on Stackoverflow, as there were multiple issues into the same direction previously.

      Author's profile photo Martin Blust
      Martin Blust

       

      Hi Philipp,

      great article!

      You find the relevant documentation for the Cloud Foundry Environment of SAP Cloud Platformcan in the  product page of the Authorization and Trust Management service. The service exists for Neo and Cloud Foundry.

      You can configure authentication for the following applications:

      If application developers need to set up authorizations for business users, they find a guide that describes how to configure scopes and attributes in role templates (see Set Up Security Artifacts).

      Administrators perform the steps of assgning security admiins, establishing trust with identity providers, aggregating roles in role collections and assigning the role collections to users or user groups (see Administration: Managing Authentication and Authorization).

       

      Author's profile photo Anuj Mehta
      Anuj Mehta

      Hi,

      The following link used to describe security without Spring is not working anymore. Please update.

      "If you do not want to use Spring Security please follow the steps here, nonetheless, the concepts described hereinafter apply for both methods."

       

      Thanks!

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Anuj,

      yes, the link unfortunately moved. You can now find it here: https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/ead7ee64f96f4c42bacbf0ae23d4135b.html . I also fixed the URL in the document above.

      The approach is also described in the book "Extending SAP S/4HANA" in chapter 5 in more detail.

      For protecting Node.js based applications you can find the documentation here: https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/4902b6e66cbd42648b5d9eaddc6a363d.html

      Best regards

      Philipp

       

      Author's profile photo Irfan Gokak
      Irfan Gokak

      Dears,

       

      I have gone through your tutorial. Everything is working fine in the local test run. But after deploying same application on Neo environment only HelloWorldServlet is working, when i try to run PurchaseOrderServlet I’m getting NOT FOUND error. Please help.

       

      https://firstappa6e0f46c9.hana.ondemand.com/firstapp-application/purchaseorders

       

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Irfan,

      the tutorial is about CloudFoundry and not Neo. Please use Step 8 of the S/4HANA Cloud SDK Tutorial to protect a Neo application. The architecture for doing this, is quite different.

      Best regards

      Philipp

      Author's profile photo Irfan Gokak
      Irfan Gokak

      Thank You. I'll follow the tutorial.

      Author's profile photo Eric Tang
      Eric Tang

      Hi Philipp,

      Thanks for your great sharing.

      Now, my back-end service is already secured, and can be visited through app router.  App router redirect the request to IDP( Identity Provider) for login, and then forward the JW token to back-end service.  it works fine for the request coming front-end.

      but now, I get an issue on accessing the back-end service in batch model. I need to store the credential(username and password) of IDP in somewhere, then using the user name/password to access the back-end service.

      for example, is there any way like to visit the back-end service using 'Post Man' by passing the username and password which similar with batch access with username/password.

      Regards,

      Eric

       

       

       

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Eric,

      I do not fully get your requirement. Do you want to access the backend directly?

      If yes, you need to implement the OAuth logic that the AppRouter does for you yourself using the standard OAuth APIs of the XSUAA. This is, for example, described here: https://blogs.sap.com/2018/08/31/how-to-get-an-access-token-from-the-xsuaa-service-for-external-api-accesses-using-the-password-grant-with-client-and-user-credentials-method/

      Again, you will never access the backend directly with the user information from the IdP but always via a JWT (OAuth Access Token).

      Best regards

      Philipp

      Author's profile photo Dama Ramesh
      Dama Ramesh

      I am able to login Hello world application(https://blogs.sap.com/2017/05/19/step-3-with-sap-s4hana-cloud-sdk-helloworld-on-scp-cloudfoundry/) using approuter login (https://blogs.sap.com/2017/07/18/step-7-with-sap-s4hana-cloud-sdk-secure-your-application-on-sap-cloud-platform-cloudfoundry/)

      But Getting Forbidden in browser while sending POST requests.

      • Getting Login page when I hit the approuter URL
      • Able to route my custom application after login and I enrolled my custom form and clicked on NEXT button. (It’s POST form submission)
      • Getting Forbidden in browser after clicking the NEXT button

      Please provide the solution for handling GET, POST, PUT, DELETE requests.

      Thank you,

      Dama Ramesh

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Dama,

      well, this may have a couple of reasons and it is hard to tell without having stack traces or looking at additional config files. Reasons include:

      • The resource is not correctly protected (i.e., whitelisted in web.xml or spring-security)
      • The resource is correctly protected but the user does not have the corresponding permissions
      • The JWT is somehow wrong
      • etc.
      • etc.

      I kindly ask you to provide your stacktrace and additional information via https://stackoverflow.com/questions/tagged/s4sdk or via https://answers.sap.com/tags/73555000100800000895.

      Thanks

      Philipp

      Author's profile photo Dama Ramesh
      Dama Ramesh

      No luck Philipp, pls check my logs.

      https://answers.sap.com/questions/679866/403-forbidden-on-browser-while-post-form-submissio.html

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Dama,

      seems like you have an issue with the CSRF protection. As written on your question please either provide a CSRF Token or disable the protection temporarily. The default behavior for any modifying operations is that a CSRF protection is required to avoid session riding attacks in productive cloud applications.

      I highly recommend you to read Chapter 5 of "Extending S/4HANA" in case you want more theoretical and conceptual background on this: https://s3-eu-west-1.amazonaws.com/gxmedia.galileo-press.de/leseproben/4655/reading_sample_sappress_1715_ExtendingSAPS4HANA.pdf

       

      Best regards

      Philipp

      Author's profile photo Dama Ramesh
      Dama Ramesh

      Thank you Philipp, My issue solved with given approach.

      https://answers.sap.com/answers/680883/view.html

      Author's profile photo Sander Wozniak
      Sander Wozniak

      Update

      As of today, the following dependencies should be sufficient for the spring security setup (also note the exclusion of log4j, the archetype uses logback by default):

      <dependency>
        <groupId>com.sap.xs2.security</groupId>
        <artifactId>java-container-security</artifactId>
        <exclusions>
          <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
          </exclusion>
        </exclusions>
      </dependency>
      <dependency>
        <groupId>org.springframework.security.oauth</groupId>
        <artifactId>spring-security-oauth2</artifactId>
      </dependency>
      <dependency>
        <groupId>com.sap.security.nw.sso.linuxx86_64.opt</groupId>
        <artifactId>sapjwt.linuxx86_64</artifactId>
        <version>1.1.19</version>
      </dependency>

      In addition, the XML schema definitions have to be updated when using the latest SDK version. The spring-security.xml file now looks like this (note the updated XML schema definitions):

      <?xml version="1.0" encoding="UTF-8" ?>
      <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:oauth="http://www.springframework.org/schema/security/oauth2"
             xmlns:sec="http://www.springframework.org/schema/security"
             xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2
              http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
              http://www.springframework.org/schema/security
              http://www.springframework.org/schema/security/spring-security-4.2.xsd
              http://www.springframework.org/schema/beans
              http://www.springframework.org/schema/beans/spring-beans-4.3.xsd">
      
          <sec:http pattern="/**" create-session="never"
                    entry-point-ref="oauthAuthenticationEntryPoint"
                    access-decision-manager-ref="accessDecisionManager"
                    authentication-manager-ref="authenticationManager"
                    use-expressions="true">
              <sec:anonymous enabled="false" />
      
              <!-- Example: Check a specific OAuth Scope (i.e., authorization) on a resource -->
              <!--<sec:intercept-url pattern="/hello" access="#oauth2.hasScope('${xs.appname}.Display')" method="GET" />-->
      
              <!-- Example: Check only authentication on a resource -->
      
              <sec:intercept-url pattern="/**" access="isAuthenticated()" method="GET" />
      
              <sec:custom-filter ref="resourceServerFilter" before="PRE_AUTH_FILTER" />
              <sec:access-denied-handler ref="oauthAccessDeniedHandler" />
          </sec:http>
      
          <bean id="oauthAuthenticationEntryPoint"
                class="org.springframework.security.oauth2.provider.error.OAuth2AuthenticationEntryPoint">
          </bean>
      
          <bean id="oauthWebExpressionHandler"
                class="org.springframework.security.oauth2.provider.expression.OAuth2WebSecurityExpressionHandler">
          </bean>
      
          <bean id="accessDecisionManager"
                class="org.springframework.security.access.vote.UnanimousBased">
              <constructor-arg>
                  <list>
                      <bean class="org.springframework.security.web.access.expression.WebExpressionVoter">
                          <property name="expressionHandler" ref="oauthWebExpressionHandler" />
                      </bean>
                      <bean class="org.springframework.security.access.vote.AuthenticatedVoter"  />
                  </list>
              </constructor-arg>
          </bean>
      
          <sec:authentication-manager alias="authenticationManager"/>
      
          <oauth:resource-server id="resourceServerFilter"
                                 resource-id="springsec" token-services-ref="offlineTokenServices" />
      
          <bean id="offlineTokenServices"
                class="com.sap.xs2.security.commons.SAPOfflineTokenServices">
              <property name="verificationKey" value="${xs.uaa.verificationkey}" />
              <property name="trustedClientId" value="${xs.uaa.clientid}" />
              <property name="trustedIdentityZone" value="${xs.uaa.identityzone}" />
          </bean>
      
          <bean id="oauthAccessDeniedHandler"
                class="org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler" />
      
          <!-- define properties file =========================================================== -->
          <bean class="com.sap.xs2.security.commons.SAPPropertyPlaceholderConfigurer">
              <property name="location"  value="classpath:/application.properties" />
          </bean>
      </beans>
      Author's profile photo Dama Ramesh
      Dama Ramesh

      <sec:intercept-url pattern="/public/hello" access="permitAll" method="GET" />

      <sec:intercept-url pattern="/**" access="isAuthenticated()" method="GET" />

      Above lines configured in my spring-security.xml.

      I am able to get http://localhost:5000/private/user page after approuter login.

      But unauthorized page getting while hitting http://localhost:8080/public/hello

      Can you please suggest me how to ignore /public/** like api's from approuter login

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Dama,

      in general, this is a Spring security question and I recommend to check with the corresponding communities. From what I can tell high-level is, that interceptor precedence is based on the order in the XML file as written here: https://stackoverflow.com/questions/15998746/order-of-intercept-url-patterns-in-spring-security. (Mind the spring-security tag there for Stackoverflow). That is, more specific rules should come first. However, this is what you did.

      I would try the following things:

      • Remove the second rule (is access allowed then with direct access?)
      • Try /public/hello/** as first rule (browsers may send a trailing ‘/’ and then the pattern might not be recognized)

      Maybe this helps

      Philipp

      Best

      Philipp

      Author's profile photo Dama Ramesh
      Dama Ramesh

      Philipp, Is there any approuter settings to ignore <approuter-url>/public/**** like urls from XSUAA login authentication?

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Yes, this is also possible by using different source routes in the xs-app.json configuration of the approuter. This is documented here: https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/c103fb414988447ead2023f768096dcc.html

      Author's profile photo Dama Ramesh
      Dama Ramesh

      Thank you Philipp.

      Author's profile photo Guilherme Cattani
      Guilherme Cattani

      Hi Phillip. I am fairly new to CF and XSUAA and this post helped me a lot.

      Can you please explain how to get things like users full name (rather than only the email in the troubleshoot) and other information like role collection from SAP IDP through CF.

      Is there an endpoint on CF that hold this information?

       

      If not, can you please point me to where to find this info?

      I am currently developing a UI5 app and would require this info to tailor the experience of the user.

       

      Thank you!

      Cheers,

      Guilherme

      Author's profile photo Dennis Hempfing
      Dennis Hempfing

      Hi Guilherme,

      you can try the following: In the xs-config.json used to configure your XSUAA instance, you can build a role such like this:

      {
      	"name": "Authenticated",
      	"description": "All authenticated users",
      	"attribute-references": [ 
      		"given_name", 
      		"family_name",
      		"email"
      	]
      }

      Now you can configure in the roles section of your IdP (by default the IdP that Cloud Foundry provides, which you can access via the “Security” tab on the left) how these fields are populated. There you should be able to select “Identity Provider” for these fields.

      If this setups works, you should now be able to read these attributes from the JWT (which you can get via the AuthTokenAccessor).

      Alternatively you can also the UserAccessor like this:

      final User currentUser = UserAccessor.getCurrentUser();
      
      currentUser.getAttribute("email");
      

      Hope that helps! Do not hesitate to get back to us with further questions!

      Best regards

      Dennis

      Author's profile photo Guilherme Cattani
      Guilherme Cattani

      Hi Dennis! Thank you very much for your reply!

      We were able to import attributes to CF successfully.

       

      We are trying to get the info in a Spring controller class now, but we are unsure how to access AuthTokenAcessor and UserAcessor.

      We were unable to load Maven dependencies correctly, for com.sap.cloud.sdk.cloudplatform.security.AuthTokenAccessor or com.sap.cloud.sdk.cloudplatform.security.user.UserAccessor.

       

      Can you please point out what are the correct dependencies and imports needed for them?

      Thank you again,

      Best regards,

      Guilherme

      Author's profile photo Dennis Hempfing
      Dennis Hempfing

      Hi Guilherme,

      glad to hear it worked!

      The following dependency is probably missing in your project:

      <dependency>
          <groupId>com.sap.cloud.s4hana.cloudplatform</groupId>
          <artifactId>security-scp-cf</artifactId>
          <version>2.8.0</version>
      </dependency>

      Alternatively, you can use scp-cf to get all the Cloud Foundry specific dependencies at once.

      Imports should ideally be handled automatically for you by your IDE. For reference, these are the correct imports:

      import com.sap.cloud.sdk.cloudplatform.security.AuthTokenAccessor;
      import com.sap.cloud.sdk.cloudplatform.security.user.UserAccessor;

      Best regards,

      Dennis

      Author's profile photo Guilherme Cattani
      Guilherme Cattani

      Hi Dennis! Thank you so much, it worked, again!

       

      Though now it has been somewhat of a problem to get the attributes correctly set in CF.

      I assigned them per role, using the Identity Provider (SAML) as source, and some attribute values that I got from here https://help.sap.com/viewer/6d6d63354d1242d185ab4830fc04feb1/Cloud/en-US/d361407d36c5443298a909acbbd96ec4.html

       

      But nothing is showing up when I try to get any of these attributes. I expected the IdP to fill them up automatically after logging in and trying to fetch them.

      How can properly set them? Is the expected Value/SAML Value different?

       

      Thanks again for your help,

      Guilherme

      Author's profile photo Dennis Hempfing
      Dennis Hempfing

      Hi Guilherme,

      stupid question: have you made sure that the role your adding all the attributes to is also assigned to the user your testing this with?

      Best regards
      Dennis

      Author's profile photo Dama Ramesh
      Dama Ramesh

      Hello Dennis,

      For me also getting empty values like below after assigning "role" to the tested user.

      email=CollectionUserAttribute(name=email, values=[])

      Please suggest me what I missed?

      https://stackoverflow.com/questions/53516649/user-profile-json-data-from-sap-cp-cf-environment/53517048?noredirect=1#comment94052857_53517048

      Author's profile photo Dennis Hempfing
      Dennis Hempfing

      Hi Guilherme, hi Dama,

      I can now give you the following update: If you use the default IdP on Cloud Foundry, the approach described here will not work (my bad). The reason for this is that the default IdP on Cloud Foundry does not use SAML. In such cases the JWT only holds the "given_name", "family_name" and "email", which you can access via:

      AuthTokenAccessor.getCurrentToken().get().getJwt().getClaim("email").asString();

      TL;DR: Mapping of SAML attributes does not work for the default IdP on Cloud Foundry.

      Author's profile photo Dama Ramesh
      Dama Ramesh

      Hi Dennis! Thank you very much for your reply!

      I can get email, given_name, family_name, ect with your approach

      or

      UserInfo userInfo = SecurityContext.getUserInfo();

      But I am unable to get uid: PXXXX, groups with your approach.

       

      Author's profile photo Dennis Hempfing
      Dennis Hempfing

      Hi Dama, unless you're bringing your own IdP that supports SAML, I am currently not aware of an approach to configure additional attributes. In general, you can use:

      AuthTokenAccessor.getCurrentToken().get().getJwt();

      To get the JWT as string and then use a JWT tool to parse it into a readable format to see which attributes you have access to.

      Author's profile photo Guilherme Cattani
      Guilherme Cattani

      Hi Dennis!

      I understand,

      That's unfortunate. I think that we are going to try SAP SSO instead . Provides a better experience and is more secure.

      Thanks a lot for your assistance!

      Best regards,

      Guilherme

      Author's profile photo Dileep Natarajan
      Dileep Natarajan

      Hi Philip,

      I have deployed my application “extensibilityapp” in CF trial account and pushed Approuter also. But, while adding new Role, i couldn’t see my application id  in Application Identifier list at all. Please help me to resolve this issue.

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Dileep,

      have you created an instance of the xsuaa and bound it to your applications and approuter as described in the blog. Deploying the artifacts only is not sufficient.

      Best regards

      Philipp

      Author's profile photo Mike Doyle
      Mike Doyle

      Hi Philipp, thanks for the blog.  I need some more info on the assignment of roles (to match the role template created by the app) and I've created a question on Stack Overflow.  I would appreciate it if you could help me out.   Thanks!

      https://stackoverflow.com/questions/55099865/spring-security-with-sap-s4sdk-capm-how-do-i-assign-roles-to-my-user

      cc Ekaterina Kruse Henning Heitkoetter

       

       

      Author's profile photo Mike Doyle
      Mike Doyle

      I've managed to restrict access to my OData services by specifying a scope in the route in the xs-app.json file in the router.  My question is, why do I also need to specify the scope in the spring-security.xml?  If we follow the steps above then direct access to the back-end service isn't possible, because there is no JWT.

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Mike,

      thanks for the question. I've provided some explanation to this on SO already, so kindly have a look there too in particular regarding your general auth problem from Neo to CF.

      Just for completeness, there are a couple of reasons:

      1. Handling authorizations in the AppRouter is really only a first line of defense and I do not recommend it. Remember your backend microservices are exposed to the web. If you just ask for authentication in the microservice you could theoretically call endpoints/routes which would require authorization checks (stealing the JWT, signing the JWT with arbitrary content etc.). This is unlikely, but possible. Thus, the microservice should protect against this too.

      2. Authorizations are, in most cases, tied to the semantics of the microservice/application. Often it may not be enough to just secure a route but check the authorizations programmatically in the code. This is not the case when you start with your application, but overtime it will change which leads me to the next point...

      3. Overtime your microservice may change and so can your authorizations and their semantics. How will you make sure that you do not forget to update your approuter too? Yes you can mitigate this with good end-to-end tests, but I have seen multiple microservice architectures where authorizations are maintained in multiple places leading to chaos and leaked information because developers forgot to update authorizations in other places too.

      4. Finally, changing authorizations in the AppRouter in production will lead to a forced logout of users. In particular, when you want to do continuous deployment I would rather keep the AppRouter as stable as possible and continuously deploy the microservices instead because they are stateless while the AppRouter is stateful holding the session information.

      In the end: It depends on your use case, but above are some productive observation that may happen when your application evolves.

      Hope this helps

      Philipp

      Author's profile photo Mike Doyle
      Mike Doyle

      Thanks Philipp for sharing those insights.  I made an update on SO.

      Author's profile photo Mike Doyle
      Mike Doyle

      Hi Philipp, I'm back looking at this issue now and I've updated the SO post.  If you could possibly help me out that would be much appreciated. Thanks!

      Author's profile photo Oliver Merk
      Oliver Merk

      Hi Philipp,

      is it possible to define a destination to the approuter using BasicAuthentication?

      Checking the connection returns  "401: Unauthorized"..

      I want the approuter to forward the request with an valid jwt-token to my service.

      Kind regards

      Oliver

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Oliver,

      honestly, I have never tried this. The documentation tells that a route in the approuter can be protected with authenticationType: “basic” (https://help.sap.com/viewer/65de2977205c403bbc107264b8eccf4b/Cloud/en-US/c103fb414988447ead2023f768096dcc.html).  Did you do this?

      Can you authenticate with the username and password at the approuter directly using basic authentication (e.g., from the browser)?

      Best regards

      Philipp

      Author's profile photo Sander Wozniak
      Sander Wozniak

      Please note that in the mean time, you should no longer use XS security libs mentioned above. You can simply use the ones provided at https://github.com/SAP/cloud-security-xsuaa-integration/. These are also available via Maven Central.

      Author's profile photo Mohanrajareddy Busupalli
      Mohanrajareddy Busupalli

      Hi,

      I am creating REST API's using java spring in cloud foundry. These API's should be called using other programs (example: Integration tools or other party applications). So using XSUAA i added approuter and deployed java application.

       

      The problem we are facing is:

      1. After java app deployed and app router, XSUAA binding, i can able to see clientid and client secret.
      2. Using below URL and client id and client secret as basic auth username and password, access_token is generated  https://<tenantid>.authentication.eu10.hana.ondemand.com/oauth/token?grant_type=client_credentials
      3. If i use this access token to do the java API calls, GET services are working fine. But POST servies are giving Unauthorized error.

      I followed this tutorial correctly and verified all configurations. Only POST services are giving this issue.

       

      Please help me, where could be the problem.

      Author's profile photo Philipp Herzig
      Philipp Herzig
      Blog Post Author

      Hi Mohanrajareddy,

      without further log information, I suppose your backend is protected with the CSRF Prevention Filter that will result in a forbidden status. Please see this question how to deal with this in the SDK here https://stackoverflow.com/questions/49791717/rest-with-s-4hana-cloud-sdk-tomee-archetype-project-returns-403-forbidden-on-po and please create a new issue with more background information.

      Thanks

      Philipp

      Author's profile photo Aparna I
      Aparna I

      Hi,

       

      I'm trying to evaluate security in Cloud SDK.

      Is token exchange supported as part of Cloud SDK core?

      We had a scenario to fetch the tokens based on the type of token using the cloud SDK rather than xs using the xs security library.

       

      Regards,
      Aparna

      Author's profile photo Sander Wozniak
      Sander Wozniak

      Please refer to https://stackoverflow.com/questions/56868652/token-fetch-using-xstokenrequest-in-cloud-sdk/56868909#56868909

      Author's profile photo James You
      James You

      Hi,

       

      I am trying to get the app router via SAP NPM Registry. I follow the guide to create folder , package.json and execute following command:

      npm config set @sap:registry https://npm.sap.com
      npm install

      But it does not succeed.

      Looks like we do not have that sap app router in NPM registry..

      Do you have any ideas ? Thanks in advance.

       

      Best regards,

      James You

      Author's profile photo Dennis Hempfing
      Dennis Hempfing

      For some reason npm does not accept the registry you set for the @sap scope. Can you try putting a .npmrc file next to the package.json with the following line:

      @sap:registry=https://npm.sap.com

      And then run npm install again.

      Author's profile photo James You
      James You

      Hi Dennis,

       

      Thanks a lot. It works!

       

       

      Best regards,

      James You

      Author's profile photo Dennis Hempfing
      Dennis Hempfing

      Glad to hear that!

      Author's profile photo harsha balur
      harsha balur

      Hi Phillip,

      Thanks for sharing this blog. I have a doubt though-In CF trail account, I have deployed my app and wanted to restrict the users in accessing the app. How do I allow only specific users to access the app?

      In my xs-security JSON file I have created View and Edit role templates. I am using default SAP ID Identity provider and after deploying the app, I have created a new Role collection, and have assigned the roles, can see roles templates defined. I was trying to directly assign users to this newly created role collection, by adding specific email ids(users who can access). But I see that users who are not added also can access deployed app. Please help me in this regard. Thanks!

      Regards,

      Harsha

      Author's profile photo Christoph Schubert
      Christoph Schubert

      Hi Harsha Balur,

      sorry for the late reply, this comment must have slipped through the cracks.

      After the "Use OAuth scope to authorize users" section your application (or better the /hello endpoint) should only be visible for users with the "Display" role assigned.

      Can you please verify that both of your users actually have the role assigned (following e.g. the "Troubleshooting OAuth Scopes from XSUAA" section) as well as that you have the correct spring security setup file?

      Greetings

      Chris

      Author's profile photo Arun Suresh
      Arun Suresh

      Is it possible to do a X.509 certificate based authentication?

      In integration scenarios, there would purely be a API with no app router.

      Would it be possible to call this API using mTLS?

       

      Regards,
      Arun Suresh

      Author's profile photo Alexander Duemont
      Alexander Duemont

      Hello Arun,

      The Cloud SDK does support Client Credentials Authentication for connecting to a destination. Its implementation heavily relies on the platform Destination Service. The online documentation lists Client Certificate Authentication as one of its supported features.

      If you want to establish an authentication scenario from client/browser to Java application itself without another service involved, then you would implement the process yourself. Officially the Cloud SDK only supports the approuter based scenario as described in this blog post. However we are always interested in new concepts and ideas how to improve, so please feel free to share your experiences with a custom authorization process.

      Best regards

      Alexander

      Author's profile photo Lingaswamy Ravula
      Lingaswamy Ravula

      I have deployed approuter and using SAP Default ID Service.

      After deploying Approuter, I have taken the URL of Approuter then it has asked me to give my email and password. I gave my SAP cloud platform Trail account credentials but it is not taking.

      The error message is "Unable to verify username or password. Please try again."

      Please let me know what could be the issue.

      Author's profile photo Artem Kovalov
      Artem Kovalov

      Hi Lingaswamy Ravula ,

      This is a very old blog which means you might be using an outdated dependency of version 2.0. It doesn't support some authentication mechanism used on the Business Technology Platform as of now.

      I would recommend checking our always up-to-date documentation here. Look at the Features\Connectivity section. We also have a fresh tutorial on authentication if you want smth with a step-by-step guide.

      These are all the tutorials for java that we have.

      If you see any problems after trying this out, please, report your incident here with as much relevant information as possible.

      I hope it helps!

      Author's profile photo Lingaswamy Ravula
      Lingaswamy Ravula

      Hi Artem,

       

      Thank you so much for the reply.

      The links shared are very useful and after going through them I could correct the mistakes that I have done in configuration files like manifest.yml. I have given random-route  = true in my application's manifest file which created issues. I have given static route by appending sub-domain id and changed other configuration files accordingly.

      Once again thank you so much,

      Author's profile photo Naga Valli Appana
      Naga Valli Appana

      I am trying to connect to S4HANA cloud instance from my application which was deployed in BTP.

      I have configured destination instance and gave destination details in BTP. But the connecting is failing with Security error. Looks like I need to give some certificate when configuring destination.

      I tried with the certificate that I used in my local but that is not working.

      I could connect to this S4HANA instance from my local system after ediing /etc/hosts file and after importing certificate to JRE.

       

      Please let me know how can I resolve this issue.

      Author's profile photo Johannes Schneider
      Johannes Schneider

      Hi Naga Valli Appana,

      This blog post is about an old version of the SAP Cloud SDK. Using this outdated version is not recommended if you just started developing. Instead, please use our latest version (currently 3.41.0) and also have a look at Artems anwser to learn more about how to use the SAP Cloud SDK version 3.

      If you still run into issues after migrating your application, please reach out to us by opening a ticket on our GitHub repository.

      Best regards

      Johannes

      Author's profile photo Dmitry Dedov
      Dmitry Dedov

      Hi all,

      I try to connect to real S4HANA system by this instruction

      https://github.com/SAP/cloud-s4-sdk-book/blob/course/2_3_security/docs/pages/security-setup.md

      I created the connection

      But the error appears

      2022-04-20 12:07:47.224300 The following problem occurred: error - <!DOCTYPE html><html><head><title>null</title></head><body><h1>Forbidden</body></html>,403,Forbidden
      f @ Log-dbg.js:452
      Log-dbg.js:452 2022-04-20 12:07:47.229199 Loading of data failed: undefined -

      Do you have any ideas?

      Author's profile photo Ivan Mirisola
      Ivan Mirisola

      Hi Dmitry Dedov,

      The forbidden 403 message is in HTML format. It seems to me that you have no published communication scenario on your S4/HANA Cloud tenant. I believe this relates to the lack of an API  being published or a communication user not being setup so that it can make calls to the real system.

      Are you able to consume any S4 APIs via Postman?

      Best regards,
      Ivan

      Author's profile photo Dmitry Dedov
      Dmitry Dedov

      Hi Ivan Mirisola,

      thanks for reply. I found the issue: the user assignment is set up in Role Collection, tab Users (not in Trust Configuration). Now it works!

      Best regards,

      Dmitry