Skip to Content
Technical Articles
Author's profile photo Divya Mary

Part 1 : Modeling the JWT token verification flows in SAP Cloud Platform API Management

The JWT policies of SAP Cloud Platform API Management enables you to generate, verify and decode the JWT token.  In the Blog Series : JSON Web Tokens (JWT) verification using SAP Cloud Platform API Management we have covered the modeling and configuration of JWT verification  policies for various Identity providers like SAP Cloud Platform XS UAAOkta , Azure Active Directory . In this part of the blog series, we have covered the steps for Modeling the JWT token verification policy using SAP Cloud Platform API Management.

For the verification of JWT token, you will need the public key that is associated with the private key which was used to sign your JWT token. This public key can be passed as the value field in JWT token policy or alternatively you can use a JSON representation of your public keys in JSON Web Keys ( JWKS) format. A sample JWKS response is provided in here.  Most of the Identity Providers provide an endpoint or service URL for their JWKS. At a high level, a simple JWT token verification policies would consist of the following steps :-

  • Reading of JWKS response from your Identity Providers.
  • Caching JWKS response to be used in subsequent calls.
  • Verification of JWT token with JWKS response input for public keys.

Note :- To keep the blog short, the policy modeling part is covered in this blog. Steps to create an API Proxy is covered in this tutorial.

  • Navigate to your SAP Cloud Platform API Management service from SAP Cloud Platform cockpit -> Services tab.
  • Access your API Portal service.
  • Navigate to Develop tab and select the API Proxy that you will like to protect using JWT and apply JWT token verification policies.

  • From the selected API Proxy details view, click Policies to open Policy Designer

  • Click Edit on the policy designer, to enter edit mode.

  • The policies for JWT verification would be applied to the incoming request from client application and should be enforced for all incoming calls. First, the JWKS response from SAP Cloud Platform API Management cache would be read and for reading cache you can use a Lookup cache policy.
  • Select ProxyEndPoint->PreFlow , select + button next to the Look up cache policyavailable under section Traffic Management Policies.

 

  • In the Create Policy dialog, enter a name for your policy say readCachedKeys and click Add. The name of the Lookup cache policy that you provide needs to be noted as you will be using this name in subsequent steps, like to check if the JWKS response was missing in local cache ( for the first time calls before the JWKS response is cached).

 

  • Select the newly added policy named readCachedKeys and provide the following policy snippet. In this snippet, JWKS response from a cache key named JWT_KEYS is read and this cached response is assigned to a local flow variable named JWTKeys.content. The scope is set to Global, so that JWKS cache response can be reused across multiple API Proxies.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<LookupCache async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
    <CacheKey>
        <KeyFragment>JWT_KEYS</KeyFragment>
    </CacheKey>
    <Scope>Global</Scope>
    <AssignTo>JWTKeys.content</AssignTo>
</LookupCache>

 

 

  • In case, the Lookup cache policy fails like the first time the API Proxy is called there is no cached JWKS response in SAP Cloud Platform API Management, you can use a Service callout policy to call the JWKS endpoint of your Identity Provider system.
  • Select + button next to the Service Callout available under section Extension Policies.

  • In the Create Policy dialog, enter a name for your policy say readJWKS and then click on Add. 

  • You need to execute this policy only in scenario where reading of the JWKS response from SAP Cloud Platform API Management cache fails. You can use the following condition snippet to specify the conditions to check if Lookup cache policy was successful or not. In the snippet below readCachedKeys is name of the Lookup cache policy.
 lookupcache.readCachedKeys.cachehit = false
  • Select the newly added policy named readJWKS and provide the above condition snippet in the Condition String text box.

 

  • Provide the following ServiceCallout policy snippet to invoke the JWKS endpoint of your Identity Provider and set the response to flow variable named JWTKeys. Note, based on your selected Identity Provider the JWKS endpoint would vary and URLproperty of the policy snippet would have to adjusted accordingly.
<ServiceCallout async="true" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
	<Response>JWTKeys</Response>
	<Timeout>30000</Timeout>
	<HTTPTargetConnection>
		<URL>https://your_identity_provider_jwks_url/</URL>
 	</HTTPTargetConnection>
</ServiceCallout>

  • In case, the Lookup cache policy fails or expires and the JWKS response fetched from the Identity provider would have to be on SAP Cloud Platform API Management so that it can be used in subsequent API Proxy invocations. You can use the Populate cache policy from SAP Cloud Platform API Management to cache the JWKS response.
  • Select + button next to the Populate cache policy available under section Traffic Management Policies.

 

  • In the Create Policy dialog, enter a name for your policy say cacheJWKS and then click on Add. 

 

  • As before, you need to execute this policy only in scenario where reading of the JWKS response from SAP Cloud Platform API Management cache fails. You can use the following condition snippet to specify the conditions to check if Lookup cache policy was successful or not. In the snippet below readCachedKeys is name of the Lookup cache policy.
 lookupcache.readCachedKeys.cachehit = false
  • Select the newly added policy named cacheJWKS and provide the above condition snippet in the Condition String text box.

  • Provide the following Populate cache policy snippet to cache the content of your Service callout response content ( JWTKeys.content) in cache key named JWT_KEYS. The scope of the Populate cache policy snippet is set to Global so that it can used across multiple API Proxies and the cache expiration interval is set to one day. You can adjust the cache expiration interval based on your requirement.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<PopulateCache async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
    <CacheKey>
        <KeyFragment>JWT_KEYS</KeyFragment>
    </CacheKey>
    <Scope>Global</Scope>
    <ExpirySettings>
        <TimeoutInSec>86400</TimeoutInSec>
    </ExpirySettings>
    <Source>JWTKeys.content</Source>
</PopulateCache>

 

  • Finally, you can use the verify JWT policy to verify the incoming JWT token in your incoming request to the API Proxy.  Select + button next to the Verify JWT policyavailable under section Security Policies.

Disclaimer :- JWT policies from SAP Cloud Platform API Management is not yet available in trial environment, so in your trial environment the Verify JWT policy won’t be visible.

  • In the Create Policy dialog, enter a name for your policy say verifyJWT and then click on Add. 

 

  • Select the newly created veriyJWT policy and provide the following VerifyJWT policy snippet to verify the JWT token which is signed using RS256 algorithm. In case of RS256 algorithm, you will need to specify the Public key used for the signing of the JWT token. You can use the JWKS element of the PublicKey element to provide a  reference to the flow variable JWTKeys.content which contains the JWKS response from your identity provider.
  • You can add in the issuer of your JWT token and during the validation of JWT token the issuer in the incoming token would be matched against the issuer specified in the policy. In case of mismatch in the issuer it will raise a unauthenticated error ( HTTP status code 401).  The JWT token in the incoming request would be read from authorization header ( HTTP header named authorization) in the format Bearer {access_token_in_jwt_format}.

Note:- You can use the Source element of VerifyJWT token policy to provide the source of your JWT token. If Source is not present, VerifyJWT token policy will read the JWT token from the HTTP header named authorization.

<!-- Verify JWT TOken -->
<VerifyJWT async="false" continueOnError="false" enabled="true" xmlns="http://www.sap.com/apimgmt">
    <Algorithm>RS256</Algorithm>
     <PublicKey>
    		<JWKS ref="JWTKeys.content"/>
    </PublicKey>
    <Issuer>your_jwt_token_issuer</Issuer>
</VerifyJWT>

 

  • Select Update to persist all the policy changes

 

  • Click Save to persist all the API Proxy changes.

 

The JWKS URL and the issuer for JWT token verification would vary based on your chosen Identity Provider. To configure the policies based on your chosen Identity provider refer the Blog Series : JSON Web Tokens (JWT) verification using SAP Cloud Platform API Management.

Assigned Tags

      15 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Murali Shanmugham
      Murali Shanmugham

      Thanks for posting on this topic. This has been requested a lot

      Author's profile photo Divya Mary
      Divya Mary
      Blog Post Author

      Hi Murali,

      Thanks a lot for your feedback

      Best Regards,

      Divya

      Author's profile photo Shilpa Vij
      Shilpa Vij

      Great Blog series Divya.

      Regards

      Shilpa

      Author's profile photo Divya Mary
      Divya Mary
      Blog Post Author

      Hi Shilpa,

      Thanks a lot for your kind words.

      Thanks,

      Divya

      Author's profile photo Mattias Johansson
      Mattias Johansson

      Great blog series,

       

      Is it possible to instead of using JWKS add the public key to a key store?

      Author's profile photo Divya Mary
      Divya Mary
      Blog Post Author

      Hi Mattias,

      Thanks a lot for your kind words.

      You would be able to store the public key in the key value map instead of the key store. This key value map can be read using the key value map policy and later used within the VerifyJWT token policy.

      Thanks and Best Regards,

      Divya

      Author's profile photo Mark Covey
      Mark Covey

      Divya, thank you for this blog.  It has been helpful.  In my instance of SAP APIM.  I don't see any option for verifyJWT.  Am I missing something?

       

      Author's profile photo Divya Mary
      Divya Mary
      Blog Post Author

      Hi Mark,

      Hopefully you are now able to see the JWT token policies . In case you continue to face the issue on your productive accounts, kindly raise a customer incident on the API Management component OPU-API-OD-OPS so that our DevOps team can assist you .

      Thanks,

      Divya

      Author's profile photo Francisco Ferreira
      Francisco Ferreira

      Hi Divya and SAP Community,

       

      Thanks in advance for this blog. I've been following this blog to a creation of an API using JWT and XSUAA information to connect to a certain endpoint.

      After following you part 1 and 4, i ran my service on the API Test Console in Debug mode, and i found that i have an error with status 500 in the response.

      According to the Debug feature, the error is on the verifyJWT Policy, i used your code snipet and used the my issuer url as you told in Part 4.

      Appart of the status code, the response retrieved is :

      {
      "fault":{
      "faultstring":"Invalid token: policy(java.lang.NullPointerException)",
      "detail":{
      "errorcode":"steps.jwt.InvalidToken"
      }
      }
      }

       

      • Have you gone through this error on your implementations?
      • If so, did you do any workaround that you wouldn't mind share?

       

      I've also run this on postman, passing the Bearer token in the "Authorization tab", i get status code 200 but it comes without any response when it should because if i run the service without using the API, the response comes finelly. Do you know the reason for that difference in both responses from Postman and API Test Console?

       

      Thanks in advance,

      Best Regards,

      Francisco Ferreira.

      Author's profile photo Divya Mary
      Divya Mary
      Blog Post Author

      Hi Francisco,

      The null pointer exception would mean that it API Proxy is not finding the OAuth access token . While testing the API Test Console, hope you are passing the OAuth token by clicking on the Headers tab and then setting the header name as Authorization and Header value as Bearer {access_token} format.

      For the status code 200, when being called from Postman, can you check if the call is reaching successfully your API ?

      Thanks,

      Divya

      Author's profile photo Francisco Ferreira
      Francisco Ferreira

      Hi Divya,

       

      Thank you for the response.

      When calling by Postman, it is reaching the API successfully, because in the API Debug Viewer for the API created, all the policies appear as green. I think the request might be getting stuck on the Identity provider of the application. I'm trying to see a workaround on that, like generating the bearer on a policy.

       

      Thank you for your attention,

      Best Regards,

      Francisco Ferreira

       

      Author's profile photo Venkata Ramana Sai Charan Korlam
      Venkata Ramana Sai Charan Korlam

      it worked

      Author's profile photo Charles Golfman
      Charles Golfman

      Divya Mary,

      Very good blogs :).

      I have a question around JWT authentication in SAP APIM so let's see if you could help.

      We have developed an ODATA service using SAP Cloud Programming Model (SAP CAP) and it has been deployed in SAP Cloud Foundry. Based on the SAP CAP recommendations, this ODATA service is secured with JWT authentication.

      Now, we would like to expose this ODATA service in SAP APIM for further consumption for a set of free-style UI5 apps which are not created in the same SAP CAP project where the ODATA services are created.

      What would be the steps needed in SAP APIM to enable this set-up based on JWT authentication?

      The scenario would be similar to the one defined in the link as follows but adding SAP APIM in the middle between the free style UI5 app and the backend SAP CAP services.

      https://blogs.sap.com/2020/07/22/how-to-integrate-ui5-with-sap-cap-application-as-the-destination-at-sap-cf-subaccount-level/

      Many thanks for your assistance in advance.

      C.

       

       

       

       

      Author's profile photo Subbu Iyer
      Subbu Iyer

      Hi Divya,

      Thanks for your efforts in publishing this blog series. It is very informative and seems promising for our use case.

      We are trying to integrate SAP IPS (Identity Provisioning Service) with Okta Identity provider using an SCIM v2 protocol.

      SAP IPS only provides the option to enter client credentials (Key and Secret) while Okta requires that when accessing its service apps, the token must be signed using the private key of the client. We are getting the following error "Client Credentials requests to the Org Authorization Server must use the private_key_jwt token_endpoint_auth_method"

      Do you think it would be possible to resolve this problem using SAP CPI to integrate both these applications?

      Regards,

       

      Subbu Iyer

       

      Author's profile photo Smitha Uthappa
      Smitha Uthappa

      HI Divya,

      You blog was very helpful. I would like to restrict client access to a API proxy using the audience claim in jwt.

      When a client application is create in the SAP API Hub the subscription is to a API product and the client app has access to all the APIs in the product.

      Can you provide some information on how to restrict access to an API in SAP using jwt tokens and how to pass and validate the audience and if it can be a dynamic field.