Technical Articles
OAuth2SAMLBearerAssertion flow with SuccessFactors with Quovadis-SAP destination.
![]() |
Bring your own trust!This is a follow-up article to the following mini series of blogs on the OAuth2SAMLBearerAssertion Flow with SAP BTP Destination Service. |
Abstract.
The focus of this instalment is to describe how to fully automate the implementation and the deployment of the OAuth2SAMLBearerAssertion flow with SAP BTP Destination service APIs, including when using your own x.509 trust with the destination. Disclaimer:
|
Scenario A.Using the generic (default) Destination Service trust
That’s the scenario covered in my original post: OAuth2SAMLBearerAssertion Flow with the SAP BTP Destination Service. SuccessFactors. Leveraging the Destination Service x.509 trust service simplifies the implementation of the entire OAuth2SAMLBearerAssertion flow, making it sort of out-of-the-box.
The above statement is, to some extent, no longer true as SAP BTP destination service has added a new REST API endpoint allowing you to download the generic SAML IdP metadata (that precisely contains the x.509 certificate) , namely /saml2Metadata. |
Let’s see what it takes to use a custom X509 certificate key pair with the destination service. |
Scenario B.Using the SuccessFactors generated X.509 key pair
Indeed, Destination Service certificate APIs allow to manage your own key-stores with certificates and have them assigned to destinations programmatically. Let’s see how this can be done with a custom trust (certificate) generated by a SFSF tenant (Admin Center/Manage OAuth2 Client Applications) |
Putting it all together.
a. Steps on the SFSF tenant side:
- Goto Admin Center/Tools/Manage OAuth2 Client Applications
- Register/add new client application.
- Generate x509 certificate. Only the CN field is mandatory. The value you enter as CN will become the name of the issuer in the signed saml assertion
- Download the generated key pair into a local text file. You will need it later.
- Register the application.
Good to know:
|
b. Next step is to convert the key pair into a keystore file format that will be accepted by the DestinationService.
Good to know:
|
Steps to create a key pair container :
- prepare the private and public keys in a normalised PEM format.
- base64-decode the PKCS8 private key into a string and then format the string into a Private Key PEM format (not exceeding 64 characters per single line),
- Save it locally into a file:
Quovadis-SAP-pkcs8.pem here goes a truncated private key content. please note each line does not exceed 64 characters ----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCxYAtn2l+j12U6 pDOpCmbzfKV8VhrbXAO6JepTchc/tWgZgKMf/yeUigpyeIiL60Mc4Q4jdcR40I+6 1LZYqkvSl6FrWU3T4tC4OJQzsMZeHW1FtxyplWs/xWEzGGE6q8Ve6Sdv1Nro7IEC xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx XGbjKUhAq24wXglEq0+FhBaeUEjmoccpuPVXAKWhAoGAPSmr/83IP1mcmVxy2OIC c4SxqKy7MhOwWLagp2t8MXjtYbs9PMyqtUzdqJBPpqGYhyj+TZkVJ1djyLeDNVbv 9Ivbez4r++c73GnBw3hBBpfdJb7uNHWj7ULV7ARdkhCQIA44zY8PE1kLsrEH8pfz OtpPzIFKF+JBkqFx0rTCQBA= -----END PRIVATE KEY-----
-
- base64-decode the X.509 public key into a string and then format the string into a X.509 PEM format (not exceeding 64 characters per single line).
- Save it locally into a file:
Quovadis-SAP-x509.pem here goes a truncated public key content: please note each line does not exceed 64 characters -----BEGIN CERTIFICATE----- MIIDKDCCAhCgAwIBAgIEFPqAZzANBgkqhkiG9w0BAQQFADBWMQswCQYDVQQGEwJV SzEJMAcGA1UECBMAMQkwBwYDVQQHEwAxDDAKBgNVBAoTA1NBUDEMMAoGA1UECxMD R1BPMRUwEwYDVQQDEwxxdW92YWRpcy9zYXAwHhcNMjEwMzI3MjM0NTM5WhcNNDgw xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx K4qO3rczlZgy5u3XhJrojcXa2+Q7GsyDl7k0egzXQxqklxsRbq09A96bbrqS+CjG Gi7CzwO6o1aExIHd5r6/A8moQjr1R0rlARrlTx5VF9IoyM7K1l5Vb5hQYn78M4dP dM1gsr5JLapT4c9XlKpv3HEcV8rTDZ+hS0ZwRSR6M5a+JZqKX+o3OlVx5D0= -----END CERTIFICATE-----
- create a PKCS12-formatted .pfx or .p12 keystore.
- run the below openssl command to create a PKCS12-formatted pfx keystore as depicted below:
$ openssl pkcs12 -export -inkey Quovadis-SAP-pkcs8.pem \
-in Quovadis-SAP-x509.pem -out Quovadis-SAP.pfx
Enter Export Password:
Verifying - Enter Export Password:
----------------------------------------------------------
Please make note of the password as you will need it later
in the destination definition.
-
- base64-encode the Quovadis-SAP.pfx file into a string for instance:
$cat Quovadis-SAP.pfx | base64
MIIJaQIBAzCCCS8GCSqGSIb3DQEHAaCCCSAEggkcMIIJGDCCA88GCSqGSIb3DQEHBqCCA8AwggO8AgEAMIIDtQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQI7lMw3L7cdssCAggAgIIDiDzxvv/WOYSgcwyCPZpmQoIRxc2m37ehcjNV7b51euH9+FxlGCOLB0czpqeRULGA+jFWp68KBm8Ze3vpjMB5XggXoi52bcy6kHpoT3BwmO43IZdAb7rahYRIti5daPvgs9xj2JVWuqonLcWKUzw89dhmQ0GPs57X6vpEtprMd2NcMVnSDGq173v6pUnwKS6AJ2YiqOwQPGasx2g44lNEpvrTsY85qIX094l4eJ4A8MsO1Nau3YT
########################## truncated #################################
HRtfx/RglD005qV14LmaAaYd6r5GOeYdV0YC5xHkBbWU9sh7aE5mDF/AVW2w22ji1UYHYp7qjkDImou7sbXpQMHyNrdcw/kPqsIRuP1wQLxcxegQqD9UMr3mhw8a4S6I/mqMP4rJcUGak6R35U+/9uSdZkbwIqSUIssEZ2d9vjAjtjcL5VlwcMEn7b1QR2qEdYuSPXcnskBHWFcskv0cICS3dUesSxm6/Psn4pbMpMYf+ydrOehkrAProaGftb9nNhFdThJEy2eW+9Jv9SLRX+05zYMYmUlBGArFHRUMKTYUNlf6vi4uTGL5K9lVHtJfllPxzSOBZ8GR9juzwfLd5/YrfN8zeP+j5UFBNZOOf1TXV7HRUGpC90UpTJsI4TN54+uXZBoC2xwX84I6QrPqFgeT4FIDKG0KIAo9thayo5VYa9OPuNy9fkLvQHfi0M80kNrUZKzOuGMxr7qQCwGdiRCwAC/LTn6GIQuB+NHRxYPXLiCZVYX1RBNPAIywasn4C77hjj02gNEqFFQlu1dgmcsw6s3nQyOzvs0lK3H4RYB0PWefD+N45FQoF98oTElMCMGCSqGSIb3DQEJFTEWBBRcuLmsoF0w3oYj1xllxSC9hRneWzAxMCEwCQYFKw4DAhoFAAQUPTi8wCiDIYWXJdI0tqd2XLbXSnsECAnnFfE3b2EgAgIIAA==
Good to know:
|
c. From now on you may use the certificate file encoded string with the DestinationService APIs.
Steps:
1. GET subaccountCertificates API call:
obtain the list of all uploaded certificates (key pairs) present
in your DestinationService instance.
https://destination-configuration.cfapps.eu10.hana.ondemand.com/destination-configuration/v1/subaccountCertificates
2. POST subaccountCertificates API call:
add a new keystore to the Destination service vault.
https://destination-configuration.cfapps.eu10.hana.ondemand.com/destination-configuration/v1/subaccountCertificates
3. you may again run the GET certificate or GET certificates
API to make sure yours has been recorded.
Good to know:
- Alternatively you might upload the .pfx keystore file into the DestinationService instance from the Destination Service UI.
d. Now it is time to create a new destination to the Quovadis-SAP OAuth application with our Quovadis-SAP.pfx keystore.
Steps:
- Prepare the json structure of the Quovadis-SAP destination.
- To make it more efficient we can reuse the json structure from the previously set up Quovadis-SFSF destination or any other destination you may have already defined.
- We will need to add new “KeyStorePassword” and the “KeyStoreLocation” properties and of course amend the apiKey, the clientKey and the user.
{
"Name": "Quovadis-SAP",
"Type": "HTTP",
"URL": "https://apisalesdemo2.successfactors.eu/odata/v2/User/$metadata",
"Authentication": "OAuth2SAMLBearerAssertion",
"ProxyType": "Internet",
"KeyStorePassword": "<your key store password>",
"tokenServiceURLType": "Dedicated",
"audience": "www.successfactors.com",
"companyId": "<SFSF tenant companyId>",
"authnContextClassRef": "urn:oasis:names:tc:SAML:2.0:ac:classes:PreviousSession",
"apiKey": "<Quovadis-SAP apiKey>",
"KeyStoreLocation": "quovadis-sap.pfx",
"clientKey": "<Quovadis-SAP apiKey>",
"nameIdFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
"SystemUser": "<your test user>",
"tokenServiceURL": "<SFSF tenant>/oauth/token"
}
- add your destination definition using the subaccountDestinations API calls as depicted below:
1. GET subaccountDestinations API call:
obtain the list of all destinations present in your DestinationService instance.
https://destination-configuration.cfapps.eu10.hana.ondemand.com/destination-configuration/v1/subaccountDestinations
2. POST subaccountDestinations API call:
add our new Quovadis-SAP destination to the Destination service instance.
https://destination-configuration.cfapps.eu10.hana.ondemand.com/destination-configuration/v1/subaccountDestinations
3. you may again run the GET destination to retrieve the newly
created Quovadis-SAP destination
https://destination-configuration.cfapps.eu10.hana.ondemand.com/destination-configuration/v1/subaccountDestinations/Quovadis-SAP
e. Use (=Find) the Quovadis-SAP destination to acquire the bearer access token as demonstrated below:
Find destination API call:
https://destination-configuration.cfapps.eu10.hana.ondemand.com/
destination-configuration/v1/destinations/Quovadis-SAP
Conclusion
The SAP BTP destination service is constantly evolving and has recently added /saml2Metadata endpoint that allows to retrieve the default trust programmatically. Thus indeed, from now on, a full automation is possible whether you decide using the default trust or you decide to bring your own trust… As usual, looking forward to comments and questions… |
__________
Troubleshooting
This is how to troubleshoot a saml assertion that is being generated by SAP BTP destination service:
How to troubleshoot SAP BTP OAuth2SAMLBearerAssertion destination with SuccessFactors? |
Additional resources.
SAP Business API Hub sandbox environment.Before you can configure the API hub sandbox environment you will need to have created an instance of the destination service. Please refer to the following article on the details for the sandbox environment configuration with SAP API Business Hub. Crypto section:Key File Formats: DER, PEM and PKCS #12 Explained.
Convert Certificate Files to One-Line PEM Format
|
Good info
When creating destination
is not recommended anymore per mentioned in SAP online help.
Exchanging User JWTs via OAuth2UserTokenExchange Destinations | SAP Help Portal
Do we have a better way to pass SF user ID in the destination entry?
Regards,
Nick
Hi Nick,
Sure, The focus of this blog was using a SFSF-generated x509 keypair as a trust with the SAP BTP destination service.
Indeed, in a productive scenario the user's identity should be provided as a digitally encoded user JWT token. But this implies telling the destination service the location of JWT token public x509 keys (jwks_uri property) and the user claim (user name , email address, sub, etc) so the destination service can retrieve the user's identity accordingly. That user's identity will then be propagated up to the OAuth2 service provider of the remote resource wrapped into a SAML Assertion (which is yet another identity token this time in XML format)
I speak about it at length in other blogs of the same series, namely:
https://blogs.sap.com/2021/04/12/sap-successfactors-integration-with-oauth2samlbearerassertion-flow./
https://blogs.sap.com/2021/07/12/bring-your-self-made-user-jwt-with-keycloak-oidc./
Please have a look. Come back if further questions....
kind regards
Piotr
Hi Piotr,
Thanks for your response.
I follow this blog to get this approach working and am now trying "...user's identity should be provided as a digitally encoded user JWT token...". Will check your other blogs!
Regards,
Nick
Hi Piotr,
Recently I'm working on this "OAuth2SAMLBearerAssertion" destination topic. A destination is created successfully in our BTP account.
In the last step to use the destination, I met a problem that an error is sent back instead of the access token. Here is the error log.
"error": "Retrieval of OAuthToken failed due to: Cannot determine user to propagate for OAuth2SAMLBearerAssertion destination. Either provide user_token JWT token (https://docs.cloudfoundry.org/api/uaa/version/4.7.1/index.html#user-token-grant) when retrieving the destination or configure it with SystemUser.",
The Bearer token in my request is retrieved from url https://<BTP authentication host>/oauth/token with parameters
But I don't know where to inject credentials of the end user. Could you please kindly guide me how to generate the Bearer token of the last step "e. Use (=Find) the Quovadis-SAP destination to acquire the bearer access token"?
Meanwhile, I found a wiki about requesting SAML Bearer token, here is the link https://docs.cloudfoundry.org/api/uaa/version/76.3.0/index.html#saml2-bearer-grant. I'm wondering if you add "SAML Assertion" in the request to get the token?
Thanks & Best Regards,
Lawrence
Hi Lawrence Bi
The error message you get is very verbose and pretty accurate. When it comes to SFSF, there are two main options:
Extending SAP SuccessFactors in the Cloud Foundry and Kyma Environment | SAP Help.
There is also a third option that consists of using SAPGraph service. You may have a look the my other blog where I explain this at length.
To summerize, if no good reasons to not do it, please rather go for Extending SAP SuccessFactors in the Cloud Foundry and Kyma Environment | SAP Help.
I hope that helps; regards; Piotr
Hi Piotr Tesny
Really appreciate for your reply!
My project is setup as the 1 option you mentioned in the message. When I passed the jwt token of logged user (issued by approuter) to the destination request with url "<BTP_DESTINATION_HOST>/destination-configuration/v1/destinations/<DESTINATION_NAME>", it returns "403 Forbidden".
Actually that's understandable from my perspective. I can take another request as an example here:
There is a request to retrieve "destination list" of BTP subaccount, with url "<BTP_DESTINATION_HOST>/destination-configuration/v1/subaccountDestinations/". Only "admin users" of current BTP subaccount could call it successfully because they are granted access. But "end users" of the our app don't have access to it and error is "403 Forbidden". That might be the same story to the previous url with path "/destination-configuration/v1/destinations/".
In my first post, I tried the jwt token of my "admin user". Result is quite reasonable now because no "end user" info is to be propagated to the OAuth2SAMLBearerAssertion destination.
So I'm a little bit lost here. Do you know what I missed here to retrieve access token of OAuth2SAMLBearerAssertion destination?
Thanks & Best Regards,
Lawrence
Hello Lawrence,
From your description you are saying that your project is set up as the option 1. In this case you would rather let the approuter call the destination, wouldn't you?. Not sure why you are trying to do it manually ?
Overall, I have a feeling that your BTP sub-account users may not have the sufficient Role Based Permission (RBP) on SFSF tenant side. Just pick one of your BTP users (like, for instance, yourself ) and make sure your BTP user does exist on SFSF side and has the required ODATA API access roles there.
I hope that helps; kind regards; Piotr
PS. You may refer to this excellent tutorial to gain better understanding of the users Role Based Permission (RBP) in SFSF tenants: How to initiate an OAuth connection to SuccessFactors Employee Central?
I am getting this error
Hello, The error above is self-explanatory. Please refer to the already provided explanation; I hope that helps