Skip to Content
Technical Articles
Author's profile photo James Rapp

SAP AppGyver and Proof Key for Code Exchange (PKCE) or “Striving for enterprise-grade security in SAP low-code applications”

Building applications has never been easier. With the advent of low-code solutions like SAP AppGyver, anyone can create a beautiful UI and connect it to real business applications, such as SAP S/4HANA or SAP SuccessFactors. Taking these low-code apps beyond prototyping and into production requires additional focus on areas like application authentication and authorization as well as principal propagation to backend data sources for a secure and contextual experience.


Development of low-code applications can be made easier by leveraging open APIs for data access. These APIs will require authentication when connecting to productive systems though, and they will almost certainly be secured with OAuth 2.0. OAuth 2.0 is used across cloud and on-premise applications as the industry standard for authorization and is broadly supported by SAP Identity Authentication (SAP IAS) and the SAP Business Technology Platform Authorization and Trust Management Service (SAP XSUAA).

While there are numerous authorization grant flows (see RFC6749) when using OAuth 2.0, most of them require a client ID and client secret to be sent with the request, typically as a Base64 encoded Basic Authorization header. As many developers will tell you, this is a problem for clients that persist this information. A reasonable user of the app could easily capture the request headers and gain access to the client credentials, and with them, the ability to abuse a potentially privileged account. Fortunately, the OAuth specification accounts for this problem and offers the Proof Key for Code Exchange, or PKCE, for public clients such as SAP AppGyver, where we would like to avoid sharing a client secret.

In this blog (and the supporting GitHub repo:, we will demonstrate how to:

  1. Configure an SAP Identity Authentication Service (IAS) application supported for public client usage and enabled for cross-consuming SAP XSUAA services
  2. Create an SAP AppGyver application that implements an authorization grant flow using PKCE, from an iOS device
  3. Manage access and refresh tokens, and use them with a protected SAP Cloud Application Programming (CAP) service running in the SAP BTP, Cloud Foundry runtime

Hint – There is also another sample in the GitHub repo showing you how to interact directly with the SAP XSUAA service if you don’t have an IAS tenant. Please be aware that this sample uses the standard Authorization Code flow for granting authorizations and is therefore not suitable for a productive enterprise scenario.

Let’s quickly check out the architecture and service requirements for the PKCE scenario before going into the details! Special thanks to my teammate, Martin Frick, for his immense contribution to this sample.

Architecture and requirements

Below you can find a simplified architecture of the scenario covered by this blog post and the provided GitHub repo. You will get a full understanding of the architecture pattern when reading through the rest of the story, so feel free to jump back to this diagram from time to time.

As briefly mentioned in the motivation, this blog post is supposed to give you an idea how to securely access your SAP CAP application running in your SAP BTP landscape from an SAP AppGyver app. Therefore, a few requirements and entitlements are mandatory. Whereas the Azure Active Directory integration acting as Identity Provider is optional (and not part of the step-by-step guide), the rest of architecture components are essential.


Solution Diagram on SAP BTP


Service Plan Quota
SAP Identity Authentication
Cloud Foundry Runtime MEMORY 1
Cloud Identity Services service
SAP AppGyver standard
Authorization and
Trust Management Service


Let’s get started with a short explanation of why SAP Identity Authentication is used instead of SAP XSUAA in this scenario and give you a few more details on the PKCE process.

SAP Identity Authentication Service (IAS)

Let’s first discuss why SAP Identity Authentication Service is required for PKCE, whereas most other SAP BTP scenarios including SAP CAP-based services are built using SAP XSUAA.

SAP XSUAA is an SAP specific fork of the Cloud Foundry User Account and Authentication (UAA) service. While SAP XSUAA fulfills similar tasks as SAP IAS when it comes to authenticating a user and providing access tokens, for our scenario there is one major advantage of using SAP IAS. As of today, SAP XSUAA does not support the PKCE authorization grant flow for public clients, which is a key point for our use case.

So, what is PKCE and why is it important for this use case? As already explained, the Proof Key for Code Exchange (PKCE) authorization grant flow was developed for public clients (like mobile apps), which are not capable of securely storing the client secret (e.g. on a user’s device). It is a variant of the OAuth 2.0 Authorization Code flow for authorization grants, which allows a secure authorization mechanism, but without the requirement to provide the client secret when calling the token endpoint of the authorization server.

The PKCE flow follows RFC7636 (click here) and you will find more detailed information available across the internet that is probably better than any explanation we can give here in this blog post. So check out the page for an example (click here) to learn more about this topic, and try out their nice playground (click here) to get a better understanding of the required steps.

As explained in detail in the provided links, the basic idea of the PKCE flow is to generate a random string on the client and send it to the to the authorization server as a so-called code challenge. The authorization server keeps track of the code challenge value (usually passed SHA256 encrypted) and after authorizing (meaning a user has logged in and given consents), it returns an authorization code to the client.

When the client now wants to obtain an access token using the authorization code, it has to provide the random string once again as a code verifier within the request parameters. The authorization server compares the code verifier against the stored code challenge. Only if both values match will it issue an access token to the client.


PKCE Authorize Flow


The standard OAuth 2.0 Authorization Code flow to obtain authorization grants for non-public clients (see RFC6749) requires the client secret when requesting an access token from the authorization server, whereas in the PKCE flow this is not required anymore. This mitigates the risk of your client secret being compromised, and all consequences of such a critical security issue! Private clients like web applications are usually capable of securely storing the client secret on the server side, but an attacker who decompiles an app stored on a public client may gain access to your client secret. As such, the PKCE flow has become a de-facto industry standard when it comes to public client authorization requirements.

So, let’s get back to our current scenario. As previously mentioned, SAP XSUAA does not support PKCE for authorization scenarios, but only the Authorization Code flow requiring a client secret. Therefore, in this blog we decided to use the SAP Identity Authentication service for a more realistic and enterprise ready scenario. As the SAP IAS is a major enabler of intelligent enterprise scenarios the additional time investment is worth it.

You might ask yourself now – “Sounds reasonable, but how do I get access to services in my SAP Business Technology Platform which are usually protected by SAP XSUAA and not SAP IAS?”. That’s a valid question which we will cover next. The magic word is cross-consumption..

SAP XSUAA cross-consumption

While most of the existing scenarios in the SAP BTP environment rely on authentication against SAP XSUAA (leveraging SAP IAS only as an Identity Provider) this scenario is different.

We’re interested in the PKCE approach, so the user in our use case will directly authenticate against SAP IAS, which will also handle the respective authorization grant flow. Consequently, the client will not receive an access token issued by SAP XSUAA but issued by SAP IAS. So how can this token be used to call services like an SAP CAP application, which is tightly integrated with SAP XSUAA for authentication and authorization purposes?

For these types of scenario, a feature called cross-consumption exists. It allows you to build interesting use cases relying on SAP XSUAA while at the same time using your SAP IAS instance for authentication and authorization. You just need to ensure that a few requirements are fulfilled, which make it possible to validate tokens issued by SAP IAS in an SAP XSUAA-coupled environment like CAP.

  • A trust between SAP XSUAA and SAP IAS needs to be established (click here). Please use the OpenID Connect approach for this instead of manually exchanging SAML metadata.
  • An instance of the SAP Cloud Identity Service needs to be created in your SAP BTP subaccount, including a parameter for SAP XSUAA cross-consumption. This will create a new application registration in your SAP IAS instance used for this scenario.

Feel free to check out the provided GitHub repo to find more details on these configuration steps. The cross-consumption parameter will result in access tokens issued by SAP IAS, which have the client ID of your SAP XSUAA application registration (created in SAP IAS during trust setup) in the audience parameter.


SAP XSUAA audience

Together with the issuer being a trusted OIDC provider of SAP XSUAA (again based on your trust configuration), this will allow a token exchange using your SAP IAS token and retrieving an SAP XSUAA token for it. This feature is already supported by default when using the @sap/xssec package for token validation in version 3.2.0 or higher and happens automatically under the hood.

Hint – This scenario only works for SAP XSUAA service instances using the application plan (broker plan is not supported) and does not support exchanges for client credential tokens.

Follow the steps in the provided GitHub repo to learn how the PKCE flow can be implemented in your own SAP BTP subaccount and SAP Identity Authentication instance.

SAP AppGyver with OAuth 2.0 PKCE

Once you’ve successfully integrated your SAP Identity Authentication service with your SAP BTP subaccount you can create an SAP AppGyver application, which will handle the PKCE flow interactively. You can run a BTP Booster to configure your subaccount for Low-Code / No-Code Application Development and provision an SAP AppGyver tenant, as well as an instance SAP Business Application Studio. You can also run this example out of the SAP AppGyver Community Edition, if desired.

Following the step-by-step guide provided in the GitHub repo, will result in an app including: :

  1. An authentication page that contains a WebView component. The WebView URL is set to the authorization endpoint of your SAP IAS tenant. Configuration of the URL is based on the SAP Cloud Identity Services – Identity Authentication
  2. When users enter their credentials and click logon, an onLocationChange event is fired that lets us capture the authorization code returned by SAP IAS and store it in an application variable.
  3. An HTTP request that sends the required information to the token endpoint and adds the resultant access token, refresh token, id token, and expires in values to the same application variable. The access token can then be used in subsequent Bearer calls to secure OData resources provided by SAP BTP. We will demonstrate this by accessing a simple SAP CAP service to populate user data extracted from the access token.

Additionally, we will show you several advanced topics, including:

  1. A JS polyfill to enable SAP AppGyver to generate the SH256 encrypted code challenge and code verifier locally. You can find the reason why this needed here on the SAP AppGyver forums.
  2. How to set and read the refresh token from local device storage to minimize repetitive logons.
  3. A technique to locally evaluate the refresh token’s lifetime and prompt the user to login again when it expires.

You can follow along with the steps in GitHub. Furthermore, in the repository you can find the steps for implementing the traditional, client secret-based approach for anybody without an SAP IAS instance available.

We hope you like the sample and would love to hear from you in the comments. Let us know if this topic is of interest, and whether you have any use cases in mind for applying it.

*Please note – This use-case is currently being refactored as public SAP IAS tokens (issued by the PKCE flow) do not contain the required SAP XSUAA audience anymore. Therefore, an additional token exchange is required to run the end-to-end scenario.


Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo Kevin Hu
      Kevin Hu

      Great blog.

      So my question is, should we also consider applications running in a browser as a public client and always use authorization code with PKCE flow over authorization code if possible?

      Also would be XSUAA support of PKCE on the roadmap?

      btw, I do have a provisioned tenant of IAS on my free tier account with a default plan as subscription and an application plan as instance.

      Author's profile photo James Rapp
      James Rapp
      Blog Post Author

      Hi Kevin,

      Thanks for your feedback. In general, this decision should be taken depending on what backend capabilities the app supports. For example, in applications such as SAP Analytics Cloud, there is no need, because the logon page is implemented to only display the Client ID and has an established trust with IAS. Similarly, Mobile Services has a backend server component that also facilitates this separation. The main benefit of utilizing PKCE is for applications where you would normally be forced to store the client id and secret directly in client-side javascript or similar. In those cases, PKCE would definitely be the place to go!

      Regarding XSUAA support of PKCE, unfortunately I don't know if this support is in the roadmap. But you can find the roadmap for SAP Cloud Identity here:

      Thanks very much for the insight that you have an application plan instance of SAP Cloud Identity available in your BTP free-tier account. If you're interested in setting up this pattern (with or without AppGyver) feel free to reach out.



      Author's profile photo Shridhar Shetty
      Shridhar Shetty

      Hi James Rapp

      The WebView component will not work in Web application scenario, can we use any other component for identity(IDP) handling purpose ? Is the any other way to implement this ?
      Author's profile photo Dustin Groß
      Dustin Groß

      Hi James Rapp

      in your note you wrote:

      Therefore, an additional token exchange is required to run the end-to-end scenario.

      Can you please elaborate, what further token exchange is required?



      Author's profile photo James Rapp
      James Rapp
      Blog Post Author

      Hi Dustin,

      You can find some details in this excellent post (and it's predecessors):

      It eventually comes down to the underlying CF spec:




      Author's profile photo Martin Frick
      Martin Frick

      Hi Dustin,

      just to add some quick thoughts on this. In case of Public Clients, an additional token exchange using Client Authentication is required by SAP IAS for security purposes. We've tested that exchange successfully in our sample application and hope that a standard implementation in the xssec library will be available soon.

      In the meantime, feel free to implement the additional token exchange of the "Public" SAP IAS token to the "Private" SAP IAS token as you can see below. The assertion value is the actual "Public" token. Same also works using an X.509 certificate instead of a secret.

      The token which you retrieve from that additional token exchange call, can be used to authenticate to your SAP XSUAA apps again.

      Feel free to reach out in case of further questions!



      POST /oauth2/token
      Content-Type: application/x-www-form-urlencoded
      Author's profile photo Thorsten Wolf
      Thorsten Wolf

      Hi Martin,


      thanks for clarifying. However i still don't quite unterstand the full picture:

      It is mentioned in the github readme document:

      Hint – You will not notice the exchange taking place. This feature is already integrated in to the @sap/xssec Node.js package which will recognize whether a token comes from SAP IAS or SAP XSUAA and trigger an exchange if necessary.

      So do we have to call the token exchange then manually or not? If we have to call it manually it must happen in some backend service because it also contains the client_secret thus not being PKCE compliant right?

      Some more details about my use case: I want to implement a btp service that is OAuth PKCE protected and would internally forward all traffic to a onPremise destination via the cloud connector and applying principle propagation to map to the correct on premise sap user. So that service would handle the PKCE authentication but internal traffic should go through the cloud connector and apply principle propagation.

      I got already the basic setup running by solely using XSUAA however this doesn't seem to work with PKCE but only the basic authorization code flow (with client secret) which is expected i guess since it seems still not to be supported in xsuaa.

      Here the very basic snipped of my proxy service that works fine with solely XSUAA:

      const express = require("express");
      const passport = require("passport");
      const xsenv = require("@sap/xsenv");
      const JWTStrategy = require("@sap/xssec").JWTStrategy;
      const SapCfAxios = require("sap-cf-axios").default;
      const axios = SapCfAxios("myDestination");
      const app = express();
      const services = xsenv.getServices({ uaa: "sample-proxy-uaa" });
      passport.use(new JWTStrategy(services.uaa));
      app.use(passport.authenticate("JWT", { session: false }));
      app.use("/", async function (req, res) {
        let url = req.originalUrl;
        const method = req.method.toLocaleLowerCase();
        const authorization = req.headers.authorization;
        await axios({
          method: method,
          url: url,
          headers: {
            "content-type": "application/json",
          .then((result) => {
          .catch((error) => {
            console.log("error", error);
            res.status(500).send({ error: "Error occured. Please check log files" });
      app.listen(process.env.PORT, function () {
        console.log("CloudToOnprem application started");

      but my requirement is to have this as a PKCE flow. So i don't know how/if to get the token exchange in that picture to have a true pkce authentication going on.


      I hope my question is not to complicated 🙂


      Thanks in advance!




      Author's profile photo Martin Frick
      Martin Frick

      Dear Thorsten Wolf,,

      I apologize for missing that earlier point. Now, after gaining a clearer understanding of your scenario, it seems that your use case should already be supported out of the box - at least from my naive understanding. However, I should note that I'm not certain if PKCE (Proof Key for Code Exchange) introduces any additional complexity.

      You can refer to this documentation link for further details: SAP BTP Connectivity - Configure Principal Propagation via IAS Token.

      If your requirement primarily revolves around pure principal propagation and doesn't necessitate XSUAA usage, I recommend trying to utilize the IAS token directly for principal propagation in the Cloud Connector. You can implement an IAS-based authentication strategy in Passport.js and then send your request to the connectivity proxy, including the required headers (token for connectivity proxy access and IAS token for principal propagation).

      I'd greatly appreciate it if you could let me know the results of your testing if you decide to give this approach a try.

      Wishing you success in your endeavors.

      Best regards,


      Author's profile photo Martin Frick
      Martin Frick

      Hi Thorsten Wolf, Dustin Groß,

      check out my recent blog post on how to make use of the PKCE flow in XSUAA scenarios again, by using an additional token exchange on the Approuter or CAP side.

      Mobile First – Making the SAP IAS-based Proof Key for Code Exchange (PKCE) great again! 🎉

      Feel free to reach out for any question!