
![]() | We have already seen how to generate a SAML bearer assertion token programmatically with SuccessFactors and Analytics Cloud as well as with S/4HANA on premise Now it's time to explore how to offload this task to our polyvalent SAP BTP destination service. I happened to come across this option a little bit by accident as I was exploring ways to simplify the OAuth2SAML2 setup with on premise S/4HANA ABAP server...Indeed, SAP BTP destination service is capable of many things, one of them being SAML Assertion Authentication - page 105 What initially misled me was that in order to be able to select the SAML Assertion Authentication one must choose the OnPremise proxy type [in the destination definition]. And I did not want to have to create a virtual mapping to my S/4HANA ABAP server gateway in any CloudConnector. But, as it eventually turned out, it does work without any CloudConnector and is not even calling the destination URL. Good to know:
Disclaimer:
|
To make this exercise more relevant I will be replacing the previously discussed programmatically generated saml bearer assertion with the one produced by the destination service. |
These are the two main options for getting a user's JWT token. Additionally, you may need to pass this token in the X-UserToken header of the destination service find API call. 1.
2.
As my nodejs client application is not necessarily deployed on BTP I have opted the latter approach. |
{
"owner": {
"SubaccountId": "xxxxxxxxxx-e2a9-4c17-84ec-xxxxxxxxxx",
"InstanceId": null
},
"destinationConfiguration": {
"Name": "SAML-EC_ADM_OAUTH",
"Type": "HTTP",
"URL": "https://<host>.<domain>:<port>/sap/bc/sec/oauth2/token?sap-client=666",
"Authentication": "SAMLAssertion",
"ProxyType": "OnPremise",
"KeyStorePassword": "<KeyStorePassword>",
"audience": "QJ9_666",
"authnContextClassRef": "urn:oasis:names:tc:SAML:2.0:ac:classes:x509",
"Description": "QUOVADIS-EC_ADM_OAUTH anywhere",
"KeyStoreLocation": "quovadis_ateam-isveng.p12",
"clientKey": "EC_ADM_OAUTH",
"nameIdFormat": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
"CloudConnectorLocationId": "",
"x_user_token.jwks_uri": "https://<IDP host>.<domain>/oauth2/certs",
"userIdSource": "<user claim from JWT token>" // defaults to "user_name",
other values could be "email" or "sub" etc...
},
"certificates": [
{
"Name": "quovadis_ateam-isveng.p12",
"Content": "MIIQeAIBAzCCEDIGCSqGSIb3DQEHAaCCECMEghAfMIIQGzCCCggGCSqGSIb3DQEHAaCCCfkEggn1MIIJ8TCCCe0GCyqGSIb3PG/HcO5xW0ai3ZkwPTAhMAkGBSsOAwIaBQAEFMyS26dKft/dWRSIVg/SQvDnQmaSBBQTST14Lse+rKA3igKg4Q7gzIB0mAICBAA=",
"Type": "CERTIFICATE"
}
],
"authTokens": [
{
"type": "SAML2.0",
"value": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDI6QXNzZXJ0aW9uIHhtbG5zOnNhbWwyPSJ1cm46jAtODUyZS00ODQzNmZlYjZlNjI8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjwvc2FtbDI6QXR0cmlidXRlU3RhdGVtZW50Pjwvc2FtbDI6QXNzZXJ0aW9uPg==",
"http_header": {
"key": "Authorization",
"value": "SAML2.0 PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDI6QXNzZXJ0aW9uIHhtbG5zOnNhbWwyPSJ1cm46bAtODUyZS00ODQzNmZlYjZlNjI8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjwvc2FtbDI6QXR0cmlidXRlU3RhdGVtZW50Pjwvc2FtbDI6QXNzZXJ0aW9uPg=="
}
}
]
}
<saml2:Assertion xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ID="eb2f1943-6239-4856-a4c0-1110e9222b0e" IssueInstant="2021-06-01T21:45:55.366Z" Version="2.0">
<script/>
<saml2:Issuer>quovadis/ateam-isveng</saml2:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<ds:Reference URI="#eb2f1943-6239-4856-a4c0-1110e9222b0e">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="xsd"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>M1JVj0c2Gr6KOz0dkfrwlMUCShGPWcX1c891MeSWqfg=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue> Xo1eT8mNPTMbhmIUmJjgKn64Qdo2dqZa061l46s1S4/a1sBxRJNYfFqYR/pskG/cLI38QBewqMiq zodR2DUndgZ8CV/i+P3zs7sfCbM6amQRBK1i7/rPaxfo2hRIEfYky/2YKMGuOltpx9E5ke0PgwrB lkwisTVA+RhN37QCHPSlRZFPZcdTlkDrg3fZNdwbzZ4UtOYgTE1abedS6RbZgPVQP2x9P3ZfbqLR URxawxSBbpv8OL5rDQzTH1dymR8UpftfyuvmVRe9uIAUYtY6cHdxqEoi+KaWMBsWrDOu/2IYCtkv Gij52RSFzmei6SGNjhenKo846+3mZYcxWbwZLNWwDENHbDvlh255fULCBhjEvkIgnMBmjd8jZu4w hI86HqMGwrLyDDwEF9yaznBzOSj4YJ+mOzEb73XPz/XlwX1eJFs9odge5SFv6a1zv1bRk+bvVwm7 rasQXCDhkwY8Q4GWbbLJSg3uQW+TRntSLkzTRtwGa/otZfc1Mpw5V6yM8Bx9W7qR6HgF7oH7AKxy rjhGvEyl2cQwKi1zXIOJ8FALCa1GY7wNBAZKV44Dpbsqq6UXkIE/UB+1qCzJBYktOGyrpLw4c03N 5PqyZncb3Gua1m//0/3GCbrPasTXDmT5ruMTl4y5Mw8hDGgDOURDV2+xd/L5LMZrCnaDG3SA8tA= </ds:SignatureValue>
</ds:Signature>
<saml2:Subject>
<saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"><QJ9_user_name></saml2:NameID>
<saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml2:SubjectConfirmationData NotOnOrAfter="2021-06-01T22:45:55.366Z" Recipient="https://<host>.<domain>:<port>/sap/bc/sec/oauth2/token?sap-client=666"/>
</saml2:SubjectConfirmation>
</saml2:Subject>
<saml2:Conditions NotBefore="2021-06-01T20:45:55.366Z" NotOnOrAfter="2021-06-01T22:45:55.366Z">
<saml2:AudienceRestriction>
<saml2:Audience>QJ9_666</saml2:Audience>
</saml2:AudienceRestriction>
<saml2:OneTimeUse/>
</saml2:Conditions>
<saml2:AuthnStatement AuthnInstant="2021-06-01T21:45:55.366Z">
<saml2:AuthnContext>
<saml2:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:x509</saml2:AuthnContextClassRef>
</saml2:AuthnContext>
</saml2:AuthnStatement>
<saml2:AttributeStatement>
<saml2:Attribute Name="client_id">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string">EC_ADM_OAUTH</saml2:AttributeValue>
</saml2:Attribute>
<saml2:Attribute Name="user_uuid">
<saml2:AttributeValue xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xsd:string"><user_uuid from JWT token></saml2:AttributeValue>
</saml2:Attribute>
</saml2:AttributeStatement>
</saml2:Assertion>
1. the assertion issuer must be equal to OAuth2.0 Identity Provider name on NW ABAP Side (SAML2 tcode). If the name of OAuth2.0 Identity Provider is not equal the CN name of the x509 certificate then you will need to use an additional destination service property, namely assertionIssuer to give the OAuth2.0 Identity Provider name. Otherwise the destination service will automatically use the CN name of the x509 trust in use. Please note as I am using my own trust I had to add this trust to the destination service key store and need to use the these two additional properties, namely
to refer it to the proper x509 trust.
2. nameIdFormat must be either urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified or urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress QJ9_user_name is either the business or technical user name
3. Recipient (ACS - Assertion Consumer Service endpoint), Please note ?sap-client=666 must be added otherwise the ACS will not be recognized and the assertion rejected as invalid
4. audience restriction: this is the name of the LocalProvider on QJ9 side, as depicted below:
5. client_id: this is the name of your OAuth client
|
You can use the SAML Assertion you obtained from the destination service find API call with the OAuth2.0 client token endpoint in order to obtain the bearer access token in turn for the subsequent ODATA calls. The value of assertion is accessible via authTokens[0].value |
"authTokens": [
{
"type": "SAML2.0",
"value": "PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDI6QXNzZXJ0aW9uIHhtbG5zOnNhbWwyPSJ1cm46jAtODUyZS00ODQzNmZlYjZlNjI8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjwvc2FtbDI6QXR0cmlidXRlU3RhdGVtZW50Pjwvc2FtbDI6QXNzZXJ0aW9uPg==",
"http_header": {
"key": "Authorization",
"value": "SAML2.0 PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz48c2FtbDI6QXNzZXJ0aW9uIHhtbG5zOnNhbWwyPSJ1cm46bAtODUyZS00ODQzNmZlYjZlNjI8L3NhbWwyOkF0dHJpYnV0ZVZhbHVlPjwvc2FtbDI6QXR0cmlidXRlPjwvc2FtbDI6QXR0cmlidXRlU3RhdGVtZW50Pjwvc2FtbDI6QXNzZXJ0aW9uPg=="
}
}
]
const options = {
auth: {
username: credentials.client.id,
password: credentials.client.secret
},
headers: {
'Accept': 'application/json',
}
};
var params = new URLSearchParams();
params.append('client_id', credentials.client.id);
if (scope !== '') params.append("scope", scope);
params.append('grant_type', "urn:ietf:params:oauth:grant-type:saml2-bearer");
params.append("assertion",authTokens[0].value);
let documents;
let access_token;
try {
const response = await axios.post(tokenUrl + '?sap-client=' + credentials.options.sap_client, params , options);
documents = JSON.stringify(response.data, null, 2);
access_token = response.data.access_token;
console.log(access_token);
console.log(documents);
console.log(response.status);
}
catch(error) {
console.log(error.message);
documents = JSON.stringify(error, null, 2);
};
Good to know: If your NW ABAP version has built-in support for SAML Bearer Assertion Provider, you might use the SAML Bearer Assertion in the Authorization header of ODATA calls thus bypassing the OAuth2 client brokering. However in this case the recipient of the assertion must reflect the real ACS endpoint (=the API endpoint) and no longer the OAuth client token endpoint! |
As you may have seen using the destination service comes with a certain price. In the end it is yet another tool that you may need to learn first. But certainly, the benefits outweigh the efforts. The less code you have to write and maintain the more time you can spend on the functional aspects of your solution. Enjoy SAP BTP destination service! Looking forward to hearing from you. Please post any questions and comments you may have in the add comment section below. |
ABAP acting as a Resource Server. App2App integration with OAuth2SAML2BearerAssertion flow. Implementing Employee Central Payroll (INTERNAL Login required– Authorized for SAP Customers and Partners) 1688545 - OAuth 2.0 Server in AS ABAP Troubleshooting |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
11 | |
7 | |
5 | |
3 | |
3 | |
3 | |
3 | |
3 | |
2 | |
2 |