Skip to Content
Technical Articles
Author's profile photo Lukas Schoemig

How to use REST API in SAP Analytics Cloud to update user profile in embedded scenarios

Introduction

Currently, I am employed as a Business Process Consultant in the SAP Analytics & Insight Team, primarily focusing on SAP Analytics Cloud and SAP Data Warehouse Cloud.

More and more customers are using iFrame to embed SAP Analytics Cloud into external web apps and 3rd party software, e.g. salesforce.com. By modifying the URL parameters of the embedded SAP Analytics Cloud iFrame, it is possible to hide the main menu, toolbar and pagebar and to embed SAP Analytics Cloud in the look and feel of the web app. This creates a homogeneous appearance for the enduser and results in single point of entry.

While using SAP Analytics Cloud embedded, the question on how to update the user profile settings occurs regularly.

It is possible to use the SCIM API (System for Cross-domain Identity Management) to update the user profile (e.g. changing the Data Access Language, Language or Date Formatting) and simultaneously supporting the single frontend illusion.

In this blog I describe the process of updating the user profile using the REST API based on SCIM.

Configuration Steps

Configuration SAP Analytics Cloud

I am using basic authentication against the token service. The first step is to create an Oauth client in SAP Analytics Cloud.

In SAP Analytics Cloud I go to ‘System’ – ‘Administration’ and open the tab ‘App Integration’.

Figure%201%3A%20Adding%20OAuth%20Clients%20in%20SAC

Figure 1: Adding OAuth Clients in SAP Analytics Cloud

 

By clicking on ‘Add a New OAuth Client’ a new pop-up window opens

Figure%202%3A%20create%20OAuth%20Clients%20in%20SAC

Figure 2: create OAuth Clients in SAP Analytics Cloud

I select ‘API Access’ in the ‘Purpose’-Field. My goal is to update the users, which is the reason for selecting ‘User Provisioning’ in the ‘Access’-Field. After entering the information, I click ‘Add’.

By creating the new OAuth client, I get an ‘OAuth Client ID’ and a ‘Secret’. This is important for the next steps and I copy this information to my clipboard.

Figure%203%3A%20OAuth%20Client%20Information

Figure 3: OAuth Client Information

 

General SCIM API

SAP Analytics Cloud exposes a REST API based on SCIM 2.0. This API allows you to

  • Create, read, update, and delete users and teams.
  • Set user profile preferences.
  • Assign existing roles to users and teams.

Detailed information regarding SCIM 2.0 can be found here

From now on, I need a tool called Postman. Postman is a tool to test and operate RESTful APIs. It is a client Software.

 

Basis Authentication against the token service via Postman

Open Postman

Step #1: Create a new Request

Click on GET Request

Figure%204%3A%20Create%20new%20request%20in%20postman

Figure 4: Create new request in postman

 

In the request I enter the following parameters for connecting to SAP Analytics Cloud:

  • GET: https://<SAC tenant>.authentication.<Data center>.hana.ondemand.com/oauth/token?grant_type=client_credentials
  • Authorization:
    • Select TYPE ‘Basic Auth’
    • Enter the username and the secret from our OAuth client
      • Username Postman = OAuth client ID
      • Password Postman = Secret

Figure%205%3A%20request%20OAuth%20access%20token

Figure 5: request OAuth access token

I click ‘Send’. If everything is set up correctly, I will get a response with an access token (Status 200). This token is valid for 1 hour.

 

Response:

  • 403: Not authorized
  • 400: Bad request
  • 200: OK

Figure%206%3A%20Obtain%20OAuth%20access%20token

Figure 6: Obtain OAuth access token

 

I must pass this access_token as a bearer token in the Authorization header of all following API requests. It is important to copy the access_token without “”. Having this access_token, I could already post a GET request for getting the users. For changing the users, I need an additional csrf token (Cross-Site-Request-Forgery).

 

Step #2: Obtain x-csrf-token

  • Create a new GET request
  • GET: https://<your-SAC-system>.<region>.sapanalytics.cloud/api/v1/scim/Users
  • Authorization TYPE: No Auth

Figure%207%3A%20Authorization%20Type%20for%20obtaining%20x-csrf-token

Figure 7: Authorization Type for obtaining x-csrf-token

  • Include the following headers with your GET request
    • Authorization Bearer <Access_Token> (This is the access token I know from step 1)
    • x-sap-sac-custom-auth true
    • x-csrf-token fetch

Figure%208%3A%20Headers%20for%20obtaining%20x-csrf-token

Figure 8: Headers for obtaining x-csrf-token

  • Click ‘Send’
  • If everything is set up I will get a X-csrf-token in the Headers of the response.

Figure%209%3A%20Response%20with%20x-csrf-token

Figure 9: Response with x-csrf-token

Step #3: Update user profile

For this step I need the access token and the x-csrf-token that I obtained in the previous steps.
At first, I need to retrieve the current user profile with a GET request.

  • Create a new GET request
  • GET: https://<your-SAC-system>.<region>.sapanalytics.cloud/api/v1/scim/Users/<username>
  • Authorization TYPE: No Auth
  • Include the following headers with the GET request:
    • Authorization Bearer <Access_Token> (The access token we know from step 1)
    • x-sap-sac-custom-auth true
    • x-csrf-token <x-csrf-token> (Step 2)

Figure%2010%3A%20GET%20request%20for%20user%20profile

Figure 10: GET request for user profile

  • In the response body I get all the information about the user. I copy this response body.

Now I can update the current user profile with a PUT request.

  • Change the request from GET to PUT
  • PUT: https://<your-SAC-system>.<region>.sapanalytics.cloud/api/v1/scim/Users/<username>
  • Authorization TYPE: No Auth
  • Include the following headers with the GET request:
    • Authorization: Bearer <Access_Token> (The access token we know from step 1)
    • x-sap-sac-custom-auth: true
    • x-csrf-token: <x-csrf-token> (Step 2)
  • Chose raw as format and select JSON from the dropdown box.
  • Paste the response body from the previous GET request (i.e. from the GET request which delivered user profile) to the PUT request body and change one of the parameters.

You can find all the parameters that can be changed here.

Figure%2011%3A%20Update%20user%20with%20copying%20and%20changing%20body

Figure 11: Update user with copying and changing body

 

  • If everything is correct I will get a “Status 200” notification
  • Also, I will see the updated body response of the user.
  • I can doublecheck the new settings in the SAC Profile settings.

Response:

  • 404: Not Found
  • 403: Not authorized
  • 400: Bad Request
  • 200: OK

 

Figure%2012%3A%20Profile%20settings%20SAC

Figure 12: Profile settings SAC

Conclusion

As described in the introduction, there are many more possibilities using the REST API, as the API allows you to

  • Create, read, update, and delete users and teams.
  • Set user profile preferences.
  • Assign existing roles to users and teams.

For a better understanding how the authentication works all the steps are done manually. With Postman it is also possible to automate this with variables.

Go ahead and check out the SAP Analytics Cloud APIs in your system, I am looking forward to your feedback and comments!

Assigned Tags

      19 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Martijn van Foeken
      Martijn van Foeken

      Hi Lucas,

      First of all, great blog. Nice hands-on guide on how to use SCIM.

      I have one question which I hope you know the answer to: What happens with the content of a user when you delete this via SCIM? If you delete a user via the SAC UI you get different options. Are there additional parameters available?

      Kind regards,

      Martijn van Foeken | Interdobs

      Author's profile photo Lukas Schoemig
      Lukas Schoemig
      Blog Post Author

      Hi Martijn,

      thank you very much for your feedback. Yes, you are right when deleting the user in SAC you have two options

      • Transfer all content to another user
      • Delete private files and only transfer public and shared content

      You could use the SCIM API to remove the user from SAC. Doing so will delete their personal content and public content will not be re-assigned.

      Best regards,

      Lukas

      Author's profile photo Anthony Sciascia
      Anthony Sciascia

      Hi Lukas,

       

      thanks for your very interesting blog.

      Could this scenario be used in a case where a sac report is embedded in a iframe on external web, and users don’t need to enter credentials (using a concurrent user) ?

      thanks

      Anthony

      Author's profile photo Lukas Schoemig
      Lukas Schoemig
      Blog Post Author

      Hi Anthony,

      even with SAC embedded reports you have to enter your credentials. Of course, if you are using SSO for the web app you could pass these credentials to SAC.

      Best regards,

      Lukas

      Author's profile photo Gabriel BERTHION
      Gabriel BERTHION

      thanks lukas

      Anthony

      Author's profile photo Jaewon Lee
      Jaewon Lee

      Hello Lukas,

       

      Thanks for your great blog!. It's very helpful information for me.

      I have a question about Team Provisioning API. User Provisioning API ( /api/v1/scim/Users/ ) is working fine like your blog.

      When I tried Team Provisioning API, Groups API ( /api/v1/scim/Groups ) is working. But, Team  API ( /api/v1/scim/Groups/<Team_ID> ) return not found page error(404). 

      For example, Even I can find Team ID 'AA' from Groups API return value. '/api/v1/scim/Groups/AA' is not working with 404 error.

      Have I any mistake when I call Team API?

       

      Best regards,

      Jaewon.

      Author's profile photo Lukas Schoemig
      Lukas Schoemig
      Blog Post Author

      Hi Jaewon, good catch! I have the same issue and it looks like something is not working correctly. I checked the help page but this is exactly what we do:  https://help.sap.com/viewer/298f82da4b184d1fb825b7ffe365e94a/release/en-US/a0572791c8444bda9084d8b07a982b4f.html

      I will get back to you, when I have an answer.
      Best regards,
      Lukas

      Author's profile photo Jaewon Lee
      Jaewon Lee

      Hi Lukas,

      I've found a notes # about TEAM API error.

      https://launchpad.support.sap.com/#/notes/2857395

      That API had defect in SAC Public API. As Notes, It was fixed at the 2019.24 version. But some additional setting is needed to use TEAM API as I understand.

      I hope it will help you to find answer.

       

      Best regards,

      Jaewon.

      Author's profile photo Lukas Schoemig
      Lukas Schoemig
      Blog Post Author

      Hi Jaewon, these are the only workarounds for SAC running on cloud foundry so far 🙁
      Best regards,
      Lukas

      Author's profile photo Do Hai Dang Le
      Do Hai Dang Le

      Hi Lukas,

      i can see the region of your tenant ist eu10. All cloud foundry tenants have a 2 digit number in the region (eu10, us20 etc.), don't they?

      So your tenant must be cloud foundry already.

      Best regards,

      Dang

      Author's profile photo Lukas Schoemig
      Lukas Schoemig
      Blog Post Author

      Hi Dang,

      yes, the tenant is running on CF. They are mentioning in the Notes that the issue happens on non-SAP data centers (Cloud Foundry / CF).

      The workaround creating the teams using SCIM API instead of creating a team through SAC it is working.

      Author's profile photo Do Hai Dang Le
      Do Hai Dang Le

      Hi,

      the response of the GET request to v1/scim/users only consists of 50 items per page.

      Do you have any idea on how to get the next page of the response or increase the number of items?

      {
          "schemas": [
              "urn:ietf:params:scim:schemas:core:2.0"
          ],
          "totalResults": 122,
          "itemsPerPage": 50,
          "startIndex": 1,
          "Resources": [
              {
                  "schemas":

      Best regards,

      Dang

      Author's profile photo Lukas Schoemig
      Lukas Schoemig
      Blog Post Author

      Hi Dang,

      the itemsPerPage are probably based on the pageination and you can't adjust them. Nevertheless, you could use the display parameters

      https://docs.wso2.com/display/IS580/Using+the+SCIM+2.0+REST+APIs#UsingtheSCIM2.0RESTAPIs-GET/FilterGroups

      In this case you will get the entries from startIndex=100

      https://<your-SAC-system>.<region>.sapanalytics.cloud/api/v1/scim/Users?startIndex=100

      Best regards,

      Lukas

      Author's profile photo Piotr Tesny
      Piotr Tesny

      Hello Lukas,

      Nice blog!

      However I recently hit a roadblock when trying to create or modify users (POST and PUT verbs). Even if I followed the documentation I would always get a 403 (forbidden) error code as a result.

      It appears that the culprit was the very usage of Postman which intercepts the cookies (from the GET call that was used to fetch the x-csrf-token in the first place) and automatically adds these cookies to the following POST/PUT/PATCH/DELETE REST API call as described here.

      I published the 403 when trying to create user with the SCIM REST API blog that explains the importance of providing the session cookie(s) that will assert the validity of the x-csrf-token.

      best regards

      Piotr

      Author's profile photo Lukas Schoemig
      Lukas Schoemig
      Blog Post Author

      Hi Piotr, thanks for clarifying and for creating the Blog related to the 403 (forbidden) error.

      Author's profile photo Patrick Melli
      Patrick Melli

      Dang,

       

      You could loop through the pages to get all the users or all the teams. I implemented the logic for a customer. Basically, pass the index the count per page to the url. Note that the count default is 50 items per pages and the max was 200

       

      // from the first query, found the statistic and get the first page.

      jsonObject = new JSONObject(responseData);

      int iTotalResult = (int) jsonObject.get("totalResults");
      System.out.println(" iTotalResult: " + iTotalResult);
      int iItemsPerPage = (int) jsonObject.get("itemsPerPage");
      System.out.println(" itemsPerPage: " + iItemsPerPage);
      int iStartIndex = (int) jsonObject.get("startIndex");
      System.out.println(" startIndex: " + iStartIndex);

      int pages = iTotalResult / iItemsPerPage;
      System.out.println("Pages " + pages);

      int modulo = iTotalResult % iItemsPerPage;
      System.out.println("Modulo " + modulo);

      ---

      get the teams or users from the first page and add them in a container

      //
      // loop on groups from one page
      //
      for (int i = 0; i < jsonArrayRessources.length(); i++) {
      JSONObject jsonSingleGroup = jsonArrayRessources.getJSONObject(i);

      jsonArrayAllTeams.put(jsonSingleGroup);

      }

       

      ---

      then get the remaining pages

      // retrieve the remaining teams

      for (int j=1;j<=pages;j++) {
      idx = j*count;

      url = sURL + _sGroupsEndPoint + "?startIndex="+idx+"&count="+count;

       


      // retrieve the remaining teams (modulo)

      idx = pages*count;

      url = sURL + _sGroupsEndPoint + "?startIndex="+idx+"&count="+count;

       

      Regards,

       

      Patrick

      Author's profile photo Vasanth Rajagopal
      Vasanth Rajagopal

      Hello Lukas,

       

      I need to trigger data load from external url into SAC using the REST API ., I created a new oath client. but i don't know how to test the API for this case. please suggest.

       

      Regards

      vasanth R

      Author's profile photo Denys van Kempen
      Denys van Kempen

      For the interested reader, we have started to record a video tutorial series about the SAP Analytics Cloud user and team provisioning API​

      • ​https://blogs.sap.com/2021/09/25/sap-analytics-cloud-user-and-team-provisioning-api-hands-on-video-tutorials/
      Author's profile photo Dan Dukan
      Dan Dukan

      Hi

      Thanks for this very instersting blog

      I'm testing API for SAC but in postman to get list of users I'm always getting HTML result:

      <!DOCTYPE html>
      <html dir="ltr" lang="en">
      <head>
          <title>Login</title>
          <meta charset='utf-8' />
          <meta name='author' content="SAP SE" />
          <meta name='copyright' content="Copyright © 2021 SAP SE. All rights reserved." />
          <meta name='robots' content='all' />
          <meta name='Description' content="" />
          <meta name='keywords' content="" />
          <meta name="viewport" content="width=device-width, initial-scale=1.0" />
          <meta name="redirect"
              content="saml/discovery?returnIDParam=idp&amp;entityID=https://xxxxxxxxxx.authentication.eu10.hana.ondemand.com&amp;idp=hanacloudservices-eu.accounts.ondema&amp;isPassive=true">
          <script>
              function samlRedirect(){var link=null;var metaElements=document.getElementsByTagName('meta');for(k=0;k<metaElements.length;k++){if(metaElements[k].getAttribute('name')==='redirect'){link=metaElements[k].getAttribute('content');};};if(link!=null&&link.length>0&&getQueryStringValue("origin")!=="uaa")location.href=link;}function getQueryStringValue(key){return decodeURIComponent(window.location.search.replace(new RegExp("^(?:.*[&\\?]"+encodeURIComponent(key).replace(/[\.\+\*]/g,"\\$&")+"(?:\\=([^&]*))?)?.*$","i"),"$1"));}samlRedirect();
          </script>
          <link href="/resources/oss/stylesheets/application.css" rel="stylesheet" />
          <link href="/resources/oss/stylesheets/sap.css" rel="stylesheet" />
          <style>
              .header-image {
                  null
              }
          </style>
      </head>
      <body class="sapUiBody" style="height: 100%; overflow: hidden;">
          <header class="sapUiSraBrandingBar sapThemeBrand-asBackgroundColor"></header>
          <div class="content">
              <div class="header">
                  <div></div>
                  <div class="header-image"></div>
              </div>
              <div class="island">
                  <h2 style="color:#666666 !important;">Welcome to xxxxxxx!</h2>
                  <div class="island-content">
                      <div>
                          <div class="saml-login">
                              <p>or sign in with: </p>
                              <div>
                                  <a href="saml/discovery?returnIDParam=idp&amp;entityID=https://xxxxx.authentication.eu10.hana.ondemand.com&amp;idp=hanacloudservices-eu.accounts.ondema&amp;isPassive=true"
                                      class="saml-login-link">hanacloudservices-eu.accounts.ondema</a>
                              </div>
                          </div>
                      </div>
                  </div>
              </div>
              <div class="footer-spacer"></div>
          </div>
          <div class="sapUiSraFooter">
              <div class="sapUiSraLoginLogo">
                  <img width="64" src="/resources/oss/images/sap.png"/>
          </div>
                  <div class="sapUiSraLoginCopyright"
                      title="Version: 74.1.0, Commit: d4c3fd3, Timestamp: 2019-09-05T21:25:00+0000, UAA: https://authentication.eu10.hana.ondemand.com">
                      Copyright © 2021 SAP SE. All rights reserved.
                  </div>
              </div>
      </body>
      </html>