Skip to Content
Technical Articles
Author's profile photo Rishabh Dhakarwal

X.509 certificate-based authentication(mTLS) – Generating X.509 certificates of BTP managed services

Written in collaboration with: Santosh Kumar

Previous Blogs:

  1. [Blog Series] X.509 certificate-based authentication(mTLS) – Demystified

Upcoming Blogs:

  1. Communication with services using SAP Destination Service(Java)
  2. Communicating with services using VCAP environment variables(Java)

Introduction:

This is the second blog in this blog post series. This blog will focus on how to generate a certificate-based service key of service and how we can extract the certificate & key and change the format as per requirements. We will also cover how we can use the generated certificate to fetch the bearer token for authenticating the service endpoints.

Content:

  1. Creating a service key with certificate credentials
  2. Updating service bindings to enable certificate-based authorization by default
  3. Generating certificate and key files from the service key
  4. Changing the format of the certificate
  5. Using Postman to fetch JWT token using the generated certificate

1) Generating a service key with certificate credentials

You might have observed that when we create a service key for any SAP-managed services, we generally get the client id and client secret for authentication. We typically use the client id and client secret to generate the JWT token from the OAuth.

By default, most SAP-managed services support x509-based authentication, but during the service key creation, it needs to be explicitly passed in the parameters.

Let’s take archiving service, the most common product service.

  • Go to your archiving service instance and create a service key without passing any parameters.
  • The service key should look like this:Client%20service%20key
  • To generate a service key with certificate and key, we need to explicitly pass the following parameter:
    {
        "xsuaa": {
            "credential-type": "x509",
            "x509": {
                "key-length": 2048,
                "validity": 7,
                "validity-type": "DAYS"
            }
        }
    }
    ​
  • The generated service key should be like this:Certificate%20service%20key

The above scenario showed that although the archiving service supported x509 authentication, the default service key generated client id and client secret. So, let’s change that!

 

2) Updating service bindings to enable certificate-based authorization by default

  • Go to the mta.yaml file of your application and update the security configuration where you define your data-archiving service instance. Now the data-archiving service will only support x509 authentication.mta.yaml%20configuration
  • Each certificate has a validity period, and we also need to provide validity to the certificate generated for the above service. The default validity will be set as 7 days.
  • The next step is to add validity to the x509 certificate. Go to your application which will be binding to the above service, and add the below config.Service%20binding
  • Now, if you again go to the data archiving service and create a service key, it should automatically generate a certificate-based credential.
  • If you go to your application which has bound with the archiving service and navigate to the Environment Variables (VCAP_SERVICES), you will see that archiving service has certificate-based credentials instead of client secret credentials.

NOTE: You can choose not to set credential-type during service definition and add only during binding. In this case, different microservices consuming the same service will have the option to choose any of the credential-type supported by the service rather than just x509

Congratulations, now you have the certificate and key to fetch the JWT token from archiving service, but how do you fetch the token?

 

3) Generating certificate and key files from the service key

Before we create the certificate and key files from the service key, we should know that there are multiple formats(extensions) in which certificate files can be stored. You can refer to more about them here

  • The next step is to extract the certificate and key in the .pem format from the service key, which can be done manually or using a bash script provided below.
  • To extract the certificate manually, please refer to this blog’s section 2(Certificate) by Carlos Roggan.
  • To generate the .pem files through the bash script, run the below command:
    sh xsuaa-x509-util.sh servicekey.json​

Where servicekey.json is the service key for archiving service

  • This will generate two files cert.pem and key.pem

Bash Script:

#!/bin/bash

if [ "$1" ]; then

  cat $1 | jq --raw-output '.uaa.key' > key.pem
  cat $1 | jq --raw-output '.uaa.certificate' > cert.pem

  KEY=`cat key.pem`
  CERT=`cat cert.pem`
  URL=`cat $1 | jq --raw-output '.uaa.certurl'`
  CLIENTID=`cat $1 | jq --raw-output '.uaa.clientid'`

  if [ "$KEY" = "null" ] || [ "$CERT" = "null" ] || [ "$URL" = "null" ] || [ "$CLIENTID" = "null" ]; then
    echo "Missing property. 'key', 'certificate', 'clientid' and 'certurl' have to be present in $1"
    exit 1
  fi

  echo "keys extracted to certificate.pem and key.pem"
  echo
  echo "curl to obtain a token:"
  echo curl  --cert cert.pem --key key.pem  -XPOST $URL/oauth/token -d "'grant_type=client_credentials&client_id="$CLIENTID"'"
else
  echo "usage: $0 <credentials.json>"
fi

 

4) Changing the format of the certificate

  • It can be done using OpenSSL if you want to convert it into .p12 format.
    openssl pkcs12 -export -out certificate.p12 -in cert.pem -inkey key.pem -passin pass:root -passout pass:root​
  • The certificates can also be converted into other formats using KeyStore Explorer. It can also be used to see more details about the certificate, like validity or issuing authority.
  • Now that we have the certificates in the required formats, we are ready to fetch the JWT token from the OAuth endpoint.

 

5) Using postman to fetch JWT token using the generated certificate

The token can also be extracted through curl using the below command:

curl --cert-type P12 --cert certificate.p12:root  -XPOST https://<oauthurl>/oauth/token -d 'grant_type=client_credentials&client_id=<clientid-in-servicekey-json>'

Using POSTMAN:

  • First, we need to add the certificate to the POSTMAN for fetching the token using the certificate.
  • Go to settings icon -> settings -> Certificates -> Add certificates
  • There are two ways to add a certificate:
    • Approach 1: We can add separate cert.pem and key.pem files
      • Host: Enter certurl from the service key
        CRT file: cert.pem (generated above)
        Key file: key.pem (generated above)
    • Approach 2: the certificate.p12 file, which is password protected
      • Host: Enter certurl from the service key
        PFX file: certificate.12 (generated above)
        Passphrase: root
  • Once the certificate is added, we can send the request to the token endpoint.
  • The token URL will be “certurl” appended with /oauth/token
  • The POSTMAN’s request should look like this:Postman%20Request

If all the steps are followed properly, the request should return the JWT token, which can be used to call the archiving service endpoints.

7) Summary:

This blog has covered how to create service keys that support certificate-based authentication. We were able to fetch the JWT bearer token to authenticate the service endpoints using curl and POSTMAN. We have also learnt how to extract the certificate from the service key and convert it to another format.
In the next blog, we will see how to use the SAP Destination service to communicate with different services using X.509 certificate.

Please let us know if you find this content helpful and share any inputs and feedback.

Assigned Tags

      8 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Divya Munnuru
      Divya Munnuru

      Your blog was extremely helpful 🙂 thank you for sharing this info

      Author's profile photo Rishabh Dhakarwal
      Rishabh Dhakarwal
      Blog Post Author

      Glad it was of help, thank you Divya 🙂

      Author's profile photo Anjaly Madhu
      Anjaly Madhu

      Thank you so much.

      We were trying to replace the client id and client secret with certificate for our BTP managed services.

      Your blogs were really helpful for us.

      Author's profile photo Rishabh Dhakarwal
      Rishabh Dhakarwal
      Blog Post Author

      Thank you so much Anjaly 🙂

      Author's profile photo Satish Kumar Kara
      Satish Kumar Kara

      Thank you so much for the detailed explanation.

      I have a different use case and facing some issue.

      I created a certificate(.pem) from BTP Cockpit -> Sub Account -> Connenctivity -> Destinations -> Certificate -> Generate Certificate

      I extracted the public key from the generated cert. I created a Master Data Integration(MDI) instance and key providing the steps there in this document

      I am creating a Destination and reading the certificate in provider account.

      I am now confused how to generate the xsuaa token. I have both cert and key in the pem file.

      Author's profile photo Rishabh Dhakarwal
      Rishabh Dhakarwal
      Blog Post Author

      Hi Satish,

      As I can see from the documentation, you can use both the certificate and key to extract the token from the uaa endpoint. Although I am not sure what would be the exact endpoint of the token URL in your case, it might be present in your MDI service instance service key. But once you have it then the below curl call should work, or you can use Postman for the same(steps are mentioned above)

      curl --cert cert.pem --key key.pem -XPOST https://security-demo.authentication.cert.eu10.hana.ondemand.com/oauth/token -d 'grant_type=client_credentials&client_id=sb-leading!t291'
      

      If you want to directly call the protected API endpoint in the code and have configured a destination, then you can refer to this documentation X.509 certificate-based authentication(mTLS) – Communicating with services using SAP destination service(Java) | SAP Blogs
      This will internally fetch the token from the Destination configuration and set the SSLContext in the HttpClient

      If you want to manually fetch the token in code you can retrieve the certificate and key from VCAP environment variable and use that token to call the protected API then you can refer to this piece of code in which we use CloudSDK libraries to fetch the token: X.509 certificate-based authentication(mTLS) – Communicating with services using VCAP environment variables(Java) | SAP Blogs

      Author's profile photo Peter Munt
      Peter Munt

      Hi Satish

      I could also created a certificate(.pem) from BTP Cockpit -> Sub Account -> Connectivity -> Destinations -> Certificate -> Generate Certificate. I can of course generate it from here but how would I extract the .PEM so I can then use it on a S4HC communication user.

      How do you do that ?

      Author's profile photo Peter Munt
      Peter Munt

      Hi Rishabh

      we have a S4H Cloud and we begun setting up on our SAP BTP the SAP Build WorkZone,standard edition (ex Launchpad).   One of the steps in the CIAS guided procedures (section 1.2 ) has a Prerequisites – X.509 client certificate
      To implement the authentication from the SAP Launchpad service to the SAP S/4HANA Cloud system, You’ve uploaded an X.509 client certificate (private and public key) to your SAP BTP subaccount 

      I had no idea about how to create this X.509 etc until I stumbled upon your Blog.  I am concerned however if your approach is the correct one for WorkZone as there is no mention in that guide about creating a service key at all and certainly not modifing the parameters like you suggest.  So does this mean they have left it out of the guided procedures and I should proceed with your suggestion?

       

      Also I read the comment by Satish that he created a certificate(.pem) from BTP Cockpit -> Sub Account -> Connenctivity -> Destinations -> Certificate -> Generate Certificate. I can do that but I do not know how to extract the certificate so I can then use it on a S4HC communication user.