Technology Blog Posts by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 
CarlosRoggan
Product and Topic Expert
Product and Topic Expert
2,182

SAP Cloud Integration (aka CPI) offers an “Advanced Event Mesh Adapter” which is well integrated with the “Advanced Event Mesh” broker.
This article shows how to set up a scenario where we send a message from iFlow via “Advanced Event Mesh Adapter” to SAP Integration Suite, Advanced Event Mesh (AEM) with OAuth Authentication.
This tutorial is based on IAS and focuses on "Client Credentials" flow.
You might be also interested in authorization code flow with IAS and client credentials with XSUAA or authorization code with XSUAA.

Technologies covered in this blog post:

  • SAP Business Technology Platform, Cloud Foundry environment (BTP)
  • SAP Cloud Integration (CPI)
  • SAP Integration Suite, Advanced Event Mesh (AEM)
  • OAuth 2.0, SAP Identity Authentication Service (IAS)

Content

0. Introduction
1. IAS: Create OAuth Client
2. AEM: Configure OAuth Settings
3. CPI: Create iFlow
4. Run Scenario
5. Optional: Use REST API
Appendix: Script for REST calls

Prerequisites

0. Introduction

We want to send a message from an iFlow to Advanced Event Mesh Broker.
We want to use the Advanced Event Mesh adapter.
Authentication should be configured with OAuth.
OAuth authorization should be provided by IAS.

This blog post is a sibling of this previous tutorial which was based on XSUAA:
https://community.sap.com/t5/technology-blogs-by-sap/sap-cloud-integration-advanced-event-mesh-adapt...

Please head over to that blog post for detailed introduction.
For now, let’s only recap the OAuth flow:  

CarlosRoggan_0-1722427590319.jpeg

 And let’s have a high-level view on our scenario:

diagram2.jpg

 In the following hands-on tutorial, we’re going through the following steps:

- Register an OAuth client at the Authorization Server (IAS).
- Configure the Resource Server to support OAuth (AEM).
- Configure the client application to use the OAuth client with “client credentials” flow (CPI).

1. IAS: Create OAuth Client

In this tutorial, we’re using IAS, but the approach should be similar when using other Authorization Servers.
We create a so-called “Application” (which represents the OAuth client) and use the credentials for configuring CPI and AEM.

1.1. Create Application

In our IAS tenant, we go to Applications & Resources -> Applications and press “Create”.
We enter a name of our choice, e.g. "iasForIflow"
and select OIDC.

1.2. Credentials

To use the application, we need credentials.
We select the new entry and in the details page we go to
Trust -> Application APIs -> Client Authentication
We scroll down to section “Secrets” and click “Add”.
There’s nothing to change, just press “Save”.
We have to take a note of Client ID and Secret.

In my example:
670d8a6f-5dda-4c5b
0AB-3efV0G@TR

 1.3. Optional: grant type

Make sure that client-credentials is enabled at
Trust -> Single Sign-On -> OpenID connect Config -> Grant Types

1.4. Optional: URLs

During our tutorial, we need some URLs to configure AEM and CPI.
They can be found at
Applications & Resources -> Tenant Settings -> Single Sign-On -> OpenID Connect Config

In this tutorial we need the token endpoint
In my example:
https://ias.accounts400.ondemand.com/oauth2/token 

And the introspection endpoint (to access token content).
In my example:
https://ias.accounts400.ondemand.com/oauth2/introspect

Always interesting to know is the public config page containing all URLs and config info of the Auth server:
https://ias.accounts400.ondemand.com/.well-known/openid-configuration 

2. AEM: Configure OAuth Authentication

Now we head over to AEM for defining the configurations required for OAuth authentication.
Our iFlow will establish a connection to AEM and will have to authenticate.
Instead of authenticating with username and password, we want to use OAuth.
As a consequence, AEM will receive a JWT token.
Which means that AEM will have to somehow check if the token can be accepted.
Below configurations enables AEM to do this validation.

At AEM, 3 steps are required:

- Enable OAuth (only once)
- Create OAuth Profile (for each OAuth client)
- Set default profile (in case of multiple profiles)

2.1. Optional: Enable OAuth Authentication

We login to AEM, click on Cluster Manager, choose our broker and click on the Manage tab.
In the section Event Broker Service Settings we click on Authentication.
We enable OAuth Provider Authentication and Save.

This step needs to be executed only once.

2.2. Create OAuth Profile

In Cluster Manager, we choose our broker and click on "Open Broker Manager".
There, we click on Messaging -> Access Control on the left navigation pane.
Below "Client Authentication" tab, we go to the sub-tab "OAuth Profiles".
To create a new profile, we click "+OAuth Profile" button and enter a name like "iasForAem".
After pressing "Create" we can start to configure this new profile.

Note:
One profile corresponds to one OAuth client.
In our case, the OAuth client is an “Application” in IAS but it could be as well an XSUAA service instance or an "Application" in Microsoft Azure AAD, etc

Settings

Enabled
yes

OAuth Client ID
Here we enter the clientid which we copied in chapter 1.3.
In my example, I enter 670d8a6f-5dda-4c5b

Change OAuth Client Secret
We should not forget to click here, although it doesn’t seem to be a field. 
Here we enter the clientsecret which we copied in chapter 1.3.
In my example, I enter 0AB-3efV0G@TR
Note:
The client secret is required for AEM to call the introspection endpoint of IAS.

OAuth Role
This is a confusing setting.
Anyways, in case of OAuth flow, we choose Resource Server.
It makes sense, because in the OAuth diagram we assigned the role of Resource Server to AEM.
With other words, this is the setting for the “client-credentials” scenario.

Issuer Identifier
Another confusing field.
We can enter any string of our choice, as long as we use it when sending a request to AEM.
This value is an ID which helps AEM to find the proper OAuth profile for an incoming JWT token.
With other words:
At the end of the day, we send a JWT token to AEM.
AEM contains multiple OAuth profiles.
So how does AEM know, which profile to use for validating the incoming token?
The answer is easy to guess:
It uses this field .
First of all, the validator reads the issuer which is carried by the JWT (the property name inside JWT token is iss).
And it searches for a profile with the same Issuer Identifier.
Alternatively, we can enter any unique string in this field.
In that case, we have to send this same string in the request, as a special property.
(Documentation can be found here)

In our tutorial, we use the IAS host.
This is the value of the iss claim in the JWT token
We use the url property from chapter 1.3 and adapt
In my example:
"ias.accounts400.ondemand.com"

Discovery Endpoint
It is not required in our scenario.
Optionally you can enter a URL like this:
https://authServer/.well-known/openid-configuration 

JWKS Endpoint
It is not required in our scenario

Introspection Endpoint
This is an endpoint which is offered by the Authorization Server (IAS).
We compose the URL by appending /introspect to the url property from chapter 1.2.
In my example:
https://ias.accounts400.ondemand.com/oauth2/introspect 
The introspect endpoint is called to validate the JWT token.
The token is sent to the endpoint and the response contains a property ("active") which indicates if the token is valid. 

Authorization Groups Claim Name
We leave this empty.

Parse Access Token
We set to disabled.
Otherwise it would fail, as the JWT token which is issued by IAS, has a different format than expected by AEM.

Validate Access Token Audience
The aud claim in a JWT token contains a list of receivers that are intended by this token.
The client itself is always in the aud.
As such, we can enable the setting and enter the clientid which we received in chapter 1.2

Validate Access Token Issuer
We can enable this validation and enter the exact issuer which is contained in the iss claim of the JWT token.
In my example:
"ias.accounts400.ondemand.com"

Validate Access Token Scope 
We disable this validation, because we cannot require a specific scope, anyways IAS doesn’t send scope in the token.

Validate Access Token Type
We can enable this validation and limit to "jwt".

aem_profile.jpg

 Finally, we can press “Apply” in the right upper corner.

2.3. Configure Default Profile

After creating an OAuth profile, it is ready to be used.
We've seen in the AEM dashboard that the new profile is added to a list of multiple OAuth profiles.
Now there's another setting in the "Client Authentication" Tab which allows to define which of the existing profiles should be used as default.

Within "Broker Manager" we go to
Access Control -> Client Authentication -> Settings
and press "Edit"
We make sure that "OAuth Authentication" is enabled.
Now we select our OAuth Profile which we created above as Default Profile Name from the drop-down.

And as usual:
Finally, we press “Apply”.

2.4. Create Username

AEM requires that the clientid is stored as username.
Otherwise we get an error "403 Client Username Is Shutdown".
We go to Broker Manager -> Messaging -> Access Control -> Client Usernames
Create new username with the clientID copied above.
We "Enable" the user and press "Apply".

2.5. Retrieve Connection details

To view the data that we need to enter in the next chapter, we go to
Cluster Manager -> Select Broker -> Connect
We open any language and choose smf-Protocol -> Get Started
We need the host and the VPN name.
In my example:
Host URI: "tcps://mr-connection-abc.messaging.solace.cloud:55443"
Message VPN: "demovpn"

Optional: View Port Config

One optional last check, to be on the safe side:
Cluster Manager -> Broker -> Manage -> Advanced Options -> Port Configuration -> Expand Public Endpoint -> click “Edit”
Expand “Solace Messaging”
Make sure that the “Secured SMF Host” is enabled and the port number matches the above: 55443

port.jpg

 

2.6. Create Queue

If not yet available, we create a queue to which we’ll send events from iFlow.
To do so, we go to
Broker Manager -> Messaging -> Queues
and create a queue with name “testqueue”.

Recap

At AEM, we’ve configured OAuth via these steps:

Broker Service
- optional: enable OAuth Authentication
Broker Manager
- create OAuth Profile
- optional: set default OAuth Profile
- create username from clientID

3. CPI: Create iFlow

At this point, the AEM broker is ready to receive JWT tokens issued for the OAuth client created in chapter 1.
Now we head over to Cloud Integration dashboard where 2 tasks are waiting for us:
- create a Security Artifact for handling the JWT token
- create an iFlow with AEM adapter for sending messages

3.1. Create Security Artifact

We create a security artifact for securely storing the credentials which we received in chapter 1.2.
CPI provides a special artifact type for OAuth 2 which is able to automatically fetch a JWT token with “Client Credentials” flow.
We go to Monitor -> Security Material
and click on Create -> OAuth 2 Client Credentials

In the dialog, we enter the following values:

Name
Any name of our choice.
Note that this name will be used in the iFlow.
In my example, I’m entering "iasForAem".

Token Service URL
This is the endpoint provided by the Authorization Server, to be used for requesting a JWT token.
We enter the value of the url property of chapter 1.4.
The full URL in my example:
"https://ias.accounts400.ondemand.com/oauth2/token"

Client ID
Here we enter the value of the clientid property which we copied in chapter 1.2.
In my example, I enter "670d8a6f-5dda-4c5b"

Client Secret
Here we enter the clientsecret property which we copied in chapter 1.2.
In my example, I enter "fIu3RGSV0G@TRyCZeN"

Client Authentication
We choose “Send as Body Parameter”.

Content-Type
We choose “application/x-www-form-urlencoded"

cpi_clicre.jpg

 

Finally, we press "Deploy".
With this, we’ve enabled CPI to fetch a JWT token for us.
Note that the credentials have to be the same as we’ve configured in the AEM profile.

3.2. Create iFlow

Now we can go ahead and create the iFlow.
In this tutorial the iFlow is as minimalistic as possible, as we only want to show the usage of the AEM adapter.

iFlow.jpg

We create a simple iFlow which does really nothing but sending messages to the Event Broker.
We define a hard-coded dummy message text.
We just want to make sure that the OAuth authentication works fine.
Let's quickly go through the steps:

Start Event
The iFlow is triggered once after deploy, by a "Timer" start event.

Content Modifier
In the "Message Body" tab we enter any dummy message text of our choice.

AEM Adapter: Connection tab
"Host":
The value for "host" is copied from AEM and pasted as is, no need to cut or append anything.
We've copied that value in chapter 2.5
In my example: "tcps://mr-connection-abc.messaging.solace.cloud:55443"

"Message VPN":
Same as above, the value of chapter 2.5.
In my example: "demovpn"

"Username":
We can leave the “default” user.

"Authentication Type":
Select “OAuth2”.

"OAuth2 Credential Type":
Choose "OAuth2 Client Credentials".

"OAuth2 Client Credentials Credential Name":
Here we enter the name of the security artifact created in chapter 3.1.
In my example: "iasForAem".

AEM Adapter: Processing tab
Here we configure our queue.

"Endpoint Type":
We select "Queue".

"Destination Name":
Here we enter the name of the desired target queue.
In my example: “testqueue”.

cpi_adapter.jpg

That’s it for iFlow creation.
BTW, saving is always a good idea.

4. Run Scenario

Now we can deploy the iFlow and check the result:

In CPI :
The log at “Monitor Message Processing” should show success message:

log.jpg

In AEM:

We go to “Broker Manager” and check the number of “Messages Queued” which should have increased.

Consume:
Another option would be to use the “Try-Me” tool in AEM to consume the messages sent from iFlow.
We go to Cluster Manager -> Select Service -> Connect
We expand "Solace Web Messaging" and copy the “Connection Details”.
Then we go to "Broker Manager" -> Try Me 
and enter the connection details and the queue name.
Immediately, we receive the messages and can check the dummy content which we specified in the “Content Modifier” step of the iFlow.

result2.jpg

With that we can be happy.

We've confirmed that OAuth authentication can be realized with CPI and AEM via AEM adapter.

5. Optional: Use REST calls

Instead of using the Broker Manager for creating an OAuth Profile, we can achieve the same via REST requests.
It is faster and it has the advantage that we can easily change parameters.
And one more good advantage: we can see the client secret that we’re configuring.
To learn about the REST APIs of AEM and how to use them, you might find this blog post helpful:
https://community.sap.com/t5/technology-blogs-by-sap/securing-sap-advanced-event-mesh-oauth-configur...

For now, let’s focus on a brief description.

5.0. Preparation

We should prepare the data that we’ll need for below REST calls.
The connection details are specific to our Broker:
It is convenient to find, we only need to go to
Cluster Manager -> Select Broker -> Manage -> Other Management Tools
Expand "SEMP - REST API"

SEMP_details.jpg

Base URL
The base URL of SEMP API that we copy contains already the path to the "config" endpoints.
In my example:
https://mr-connection-abc.messaging.solace.cloud:943/SEMP/v2/config
VPN Name
In my example: "demovpn"
Username
We're using basic authentication for calling the SEMP API.
The user is a technical user provided by AEM and we copy it from screenshot above.
In my example: "
demovpn-admin".
Password
Same as above.
In my example: "*****".
Client ID
The clientID which we stored in chapter 1.2
In my example:
"670d8a6f-5dda-4c5b"
ClientSecret

The secret which we stored in chapter 1.2
In my example: "B3efIu3RGSV0G@TRyCZe"
Introspect Endpoint
Same as above, We compose the URL by appending /introspect to the url property from chapter 1.2.
In my example:
https://ias.accounts400.ondemand.com/oauth2/introspect 

5.1. Optional: View existing OAuth profiles

The URL is specific for our new Event Broker Service, and it uses the /config API of SEMP

Request
URL
      https://mr-connection-xxx.messaging.solace.cloud:943/
           SEMP/v2/config/msgVpns/<vpn>/authenticationOauthProfiles
Method
      GET
Authentication
   user:   demovpn-admin
   password:  abcd1234
Response
   The response is a JSON structure with lot of metadata.
   Interesting for us is the "data" node
   At this moment, it is an empty JSON array

I apologize for the line break in the URL.
See here the full URL in one line:

 

 

 

 

 

 

 

https://mr-connection-xxx.messaging.solace.cloud:943/SEMP/v2/config/msgVpns/<vpn>/authenticationOauthProfiles

 

 

 

 

 

 

 

Note:
Make sure to replace the placeholders with your actual values

 
5.2. Create OAuth Profile

Before we send the request, we need to prepare the request payload for creation.
Request payload for creating OAuth profile in my example:

 

 

 

 

 

 

 

{
    "clientId": "670d8a6f-5dda-4c5b",
    "clientSecret": "abcd1234" ,
    "enabled":true,    
    "endpointIntrospection":"https://ias.acc.ondemand.com/oauth2/introspect",
    "endpointIntrospectionTimeout":10,
    "msgVpnName":"demovpn",
    "issuer": "ias.accounts400.ondemand.com",
    "oauthProfileName":"iasForIflow",
    "oauthRole":"resource-server",
    "resourceServerParseAccessTokenEnabled":false,
    "resourceServerValidateIssuerEnabled":true,
    "resourceServerRequiredIssuer":"ias.accounts400.ondemand.com",
    "resourceServerValidateAudienceEnabled":true, 
    "resourceServerRequiredAudience":"670d8a6f-5dda-4c5b",
    "resourceServerValidateTypeEnabled":true,
    "resourceServerRequiredType":"JWT",  
    "resourceServerValidateScopeEnabled":false,
    "usernameClaimName":"sub"
}

 

 

 

 

 

 

 

Note:
Make sure to adapt parts of the payload to your data.

Explanation of parameters: see this previous blog post:
https://community.sap.com/t5/blogs/blogworkflowpage/blog-id/technology-blog-sap/article-id/174242

Now we can go ahead and execute the request:

Request
URL
      https://mr-connection-xxx.messaging.solace.cloud:943/
           SEMP/v2/config/msgVpns/<vpn>/authenticationOauthProfiles
Method
      POST
Authentication
   user:   demovpn-admin
   password:  abcd1234
Headers
      name:     content-type 
      value:  application/json
Body
      The adapted JSON payload from above
Response

      If we’re lucky, we get a success code and the created profile is contained in the response body.
      If not………
      Well, it might take time to figure out the reason, because the error messages are not helpful.
      My recommendation would be to inspect and adapt the JSON.

That’it.

5.3. Delete OAuth Profile

The URL is specific for our new Event Broker Service, and it uses the /config API of SEMP

Request
URL
      https://mr-connection-xxx.messaging.solace.cloud:943/
           SEMP/v2/config/msgVpns/<vpn>/authenticationOauthProfiles/<profile>
Method
      DELETE
Authentication
   user:   demovpn-admin
   password:  abcd1234
Response
   The response is JSON metadata with success status code.

I apologize for the line break in the URL.
See here the full URL in one line:

 

 

 

 

 

 

 

https://mr-connection-xxx.messaging.solace.cloud:943/SEMP/v2/config/msgVpns/<vpn>/authenticationOauthProfiles/<profile>

 

 

 

 

 

 

 

Note:
Make sure to replace the placeholders with your actual values

                                                                               
Note:
In the appendix I’ve pasted useful scripts to run the rest calls in Node.js and Linux.

Troubleshooting

If the authentication is not configured correctly, the iFlow would fail during deployment.
The error could be seen in Monitor -> Manage Integration Content
Error message like below, security related error messages are usually not helpful:
com.solacesystems.jcsmp.JCSMPErrorResponseException: 401: Unauthorized

Status 401 indicates that the access is not allowed, token validation failed.
This means that the OAuth configuration is not correct.
Sorry that I don’t have a better explanation.

To fix it, we need to go through the tutorial again and check:
- ClientID and secret: are they the same in CPI-Security-Artifact and in AEM-OAuth-Profile?
- Is the correct Security Artifact configured in the CPI-AEM-adapter?
- Go through the OAuth profile and check each setting and URLs, deactivate the validations.
- You may want to fetch a JWT token manually (e.g. using Postman or curl) and introspect it (www.jwt.io) to view the content of the iss claim.

Sorry that I cannot give better advice.

Summary

In this blog post we've learned how to use OAuth authentication for sending messages from iFlow via AEM adapter.
We've learned that 3 configuration steps are required at AEM:

AEM Broker Service: enable OAuth Authentication
AEM Broker Manager: create OAuth Profile
AEM Broker Manager: define default OAuth Profile

And we've learned how to configure the AEM adapter for an iFlow receiver channel:
CPI Monitoring: Create security artifact for "Client Credentials"
CPI iFlow AEM adapter: use the security artifact for OAuth2 authentication.
CPI iFlow AEM adapter: Connection details are copied from "Connection" tab in AEM.

In this blog post we've used IAS as Authorization Server.
We've focused on the OAuth flow "Client Credentials".

Links

OAuth spec https://datatracker.ietf.org/doc/html/rfc6749
AEM docu https://help.pubsub.em.services.cloud.sap/Cloud/cloud-lp.htm
IAS client-credentials https://help.sap.com/docs/cloud-identity-services/cloud-identity-services/using-client-credentials-f...
Blog: AEM Adapter with authorization code with XSUAA

Blog for using "Authorization Code" flow with IAS:
https://community.sap.com/t5/technology-blogs-by-sap/sap-cloud-integration-advanced-event-mesh-adapt...

Appendix 1: cURL commands

For your convenience, I've put together the cURL commands required for above described steps.
Make sure to adapt the values of the variables.

 

 

 

 

 

 

 

# define constants
VPN="demovpn" 
SEMP_URL="https://mr-connection-xxx.messaging.solace.cloud:943/SEMP/v2/config" 
USER="demovpn-admin" 
PWD="9uumbe847rv" 

#constants for request payload
OAUTH_PROFILE_NAME='iasForIflow'
CLIENTID='670d8a6f-5dda-4c5b'
SECRET='-0AB3efIuG@TR'
HOST='ias.accounts400.ondemand.com'
BASEURL="https://${HOST}"
INTROSPECT="${BASEURL}/oauth2/introspect"

# OAuth Profile content
BODY_PROFILE='{
    "clientId":"'${CLIENTID}'",
    "clientSecret":"'${SECRET}'",
    "enabled":true,
    "endpointIntrospection":"'${INTROSPECT}'",
    "endpointIntrospectionTimeout":10,
    "msgVpnName":"'${VPN}'",
    "issuer":"'${HOST}'",
    "oauthProfileName":"'${OAUTH_PROFILE_NAME}'",
    "oauthRole":"resource-server",
    "resourceServerParseAccessTokenEnabled":false,
    "resourceServerValidateIssuerEnabled":true,
    "resourceServerRequiredIssuer":"'${HOST}'",
    "resourceServerValidateAudienceEnabled":true, 
    "resourceServerRequiredAudience":"'${CLIENTID}'",
    "resourceServerValidateTypeEnabled":true,
    "resourceServerRequiredType":"JWT",  
    "resourceServerValidateScopeEnabled":false,
    "usernameClaimName":"sub"
}'

# count existing OAuth profiles:
PROFILES=$(curl --url "${SEMP_URL}/msgVpns/${VPN}/authenticationOauthProfiles" -u "${USER}:${PWD}" -s | jq '.data | length')
echo "Found OAuth profiles: '${PROFILES}'"


# === #
# Create OAuth profile #
# === #
CREATED=$(curl --url "${SEMP_URL}/msgVpns/${VPN}/authenticationOauthProfiles" -u "${USER}:${PWD}" -H 'content-type: application/json' -s -X POST -d "${BODY_PROFILE}")
echo "Creation of OAuth Profile finished with result '${CREATED}'"

# check after creation
PROFILES=$(curl --url "${SEMP_URL}/msgVpns/${VPN}/authenticationOauthProfiles" -u "${USER}:${PWD}" -s | jq '.data | length')
echo "Found OAuth profiles: '${PROFILES}'"

# delete OAuth Profile
curl -X DELETE --url "${SEMP_URL}/msgVpns/${VPN}/authenticationOauthProfiles/${OAUTH_PROFILE_NAME}" -u "${USER}:${PWD}"

 

 

 

 

 

 

 

Appendix 2: Node.js sample code

Please find below some Node.js code that I've used to execute the tutorial.
Make sure to adapt the values.

 

 

 

 

 

 

 

const axios = require('axios')

const SEMP_URL = "https://mr-connection-xxx.messaging.solace.cloud:943/SEMP/v2/config" 
const VPN = "demovpn" 
const USER = "demovpn-admin" 
const PWD = "9uumbe847" 

const PROFILE_NAME = "iasForIflow"
const CLIENTID = "670d8a6f-5dda-4c5b"
const SECRET = "-0AB3efIuG@TR"
const HOST = "ias.accounts400.ondemand.com"
const INTROSPECT = `https://${HOST}/oauth2/introspect`

const BODY_PROFILE = {
    "clientId":CLIENTID,
    "clientSecret":SECRET,
    "enabled":true,
    "endpointIntrospection":INTROSPECT,
    "endpointIntrospectionTimeout":10,
    "issuer":HOST,
    "msgVpnName":VPN,
    "oauthProfileName":PROFILE_NAME,
    "oauthRole":"resource-server",
    "resourceServerParseAccessTokenEnabled":false,
    "resourceServerValidateAudienceEnabled":true,
    "resourceServerRequiredAudience":CLIENTID,
    "resourceServerValidateIssuerEnabled":true,
    "resourceServerRequiredIssuer":HOST,
    "resourceServerValidateTypeEnabled":true,
    "resourceServerRequiredType":"jwt",
    "resourceServerValidateScopeEnabled":false,
    "usernameClaimName":"sub"
}

/* HELPERS */

async function getOAuthProfilesForMsg(){   
    return callAxios('GET', null, `${SEMP_URL}/msgVpns/${VPN}/authenticationOauthProfiles`)
}

async function createOAuthProfileForMsg(payload){
    return callAxios('POST', payload, `${SEMP_URL}/msgVpns/${VPN}/authenticationOauthProfiles`)
}

async function deleteOAuthProfileForMsg(profileName){
    return callAxios('DELETE', null, `${SEMP_URL}/msgVpns/${VPN}/authenticationOauthProfiles/${profileName}`)
}

async function callAxios(method, payload, url){
    const auth = Buffer.from(USER + ':' + PWD).toString("base64");
    const options = {
        url: url,
        headers: {
            'Content-Type': 'application/json',
            'Authorization': 'Basic ' + auth        
        },
        method: method
    }
    if(payload){
        options.data = payload
    }

    let response = undefined
    try {
        response = await axios(options)
        return response.data
    } catch (error) {
        if (error.response) {
            console.log("===> ERROR : message: " + error.message)
            console.log("===> ERROR : status: " + error.response.status)
            console.log("===> ERROR : headers: " + JSON.stringify(error.response.headers))
            console.log("===> ERROR : internal error:" + error.response.data.error)
            console.log("===> ERROR : internal message:: " + error.response.data.message)            
        }else{
            console.log({...error}) 
        }
    }
}


/* SCRIPT */
async function run(){
    let response = await getOAuthProfilesForMsg()
    console.log("response: " + JSON.stringify(response.data))
    console.log("profiles count: " + response.data.length)

    // create
    response = await createOAuthProfileForMsg(BODY_PROFILE)
    console.log("response: " + JSON.stringify(response.data))

    // delete
    response = await deleteOAuthProfileForMsg(PROFILE_NAME)
    console.log("response: " + JSON.stringify(response))

    // check number
    response = await getOAuthProfilesForMsg()
    console.log("profiles count: " + response.data.length)

}

/* RUN */
run()