[go: up one dir, main page]

Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
CarlosRoggan
Product and Topic Expert
Product and Topic Expert

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.

Technologies covered in this blog post:
🔹SAP Business Technology Platform, Cloud Foundry environment
🔹SAP Cloud Integration
🔹SAP Integration Suite, Advanced Event Mesh
🔹XSUAA, OAuth 2.0

Content

0. Introduction
1. BTP: Create OAuth Client with XSUAA
2. AEM: Configure OAuth Settings
3. CPI: Create iFlow
4. Run Scenario

Prerequisites

🔹To follow this tutorial, access to  SAP Advanced Event Mesh is required.
🔹Access To CPI Tenant is required.
🔹Access to Subaccount in BTP with permissions to create service instances
🔹I recommend bookmarking the Security Glossary

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.

What is OAuth?
Let’s try to give a brief summary:
We don’t send user/password to the endpoint.
Instead, we send a token (a string containing some info).
We fetch that token from a so-called “Authorization Server”.
Beforehand, we have registered a “client” at that server.
Upon registration, the client gets an ID and a password, called “secret”.

To fetch a token, one of several “OAuth flows” is used.
Typical flow:
(1) the web application (“client”) requests a token from “Auth Server” (with ID / secret).
(2) The server asks the end user for consent (user enters name/password).
(3) Web app receives token and sends it (4) to the endpoint (“Resource Server”).
(5) The endpoint validates the token (with help from “Auth Server”) and responds to client.
This flow is called “Authorization Code” and requires interaction from end user.

diagram_oauth.jpg

 

Summarizing, we have 4 participants:
Resource Server, hosting the resources, that are requested by the web app (e.g. photos).
Client, the (web) application.
Authorization Server, the server which issues the access tokens and knows how to validate end users.
End User, human user who uses the web applications and owns the resources (e.g. own photos).

What is a JWT token?
It stands for JSON Web token, it is a string that contains data in JSON format.
The string is encoded with Base46.
The data contains the client ID and permissions and more.

How does it apply to CPI?
If user interaction and user information is not required, we can use “Client Credentials flow”.
It is simpler, because user consent can be skipped.
This is what we use for our scenario.

diagram2.jpg

We can see that XSUAA acts as “Authorization Server” which issues a JWT token.
The AEM represents the “Resource Server” which hosts the protected resources, in this case we connect to it for sending messages.
CPI takes the role of the client which requests a JWT token and sends client ID + secret.

To be more concrete:
Beforehand, we create an instance of XSUAA service, which involves the registration of a client at XSUAA.
The instance is the client and the credentials are obtained via service key (because we cannot bind).
The credentials are then stored in CPI as a Security Artifact (in this case: “OAuth 2 Client Credentials”).
This security artifact is configured in the AEM adapter.
CPI is then able to automatically fetch a JWT token which is sent by the AEM adapter when connecting to AEM.
At AEM side, we have to configure the information of XSUAA and the client credentials.
This enables AEM to validate the incoming JWT token (with the help of XSUAA).

In the following hands-on tutorial, we’re going to take care of each of the 3 participants:

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

1. BTP: Create OAuth Client

In this tutorial, we’re using XSUAA, but the approach should be similar when using other Authorization Servers like IAS.
We create a service instance (which represents the OAuth client) and use the credentials for configuring CPI and AEM.

1.1. Create Service instance

Go to your subaccount -> Service Marketplace -> Authorization and Trust Management -> Create
Then select the service plan as “application” and enter a name of your choice.
In my example: "xsuaaForAem".

 

createXsuaa0.jpg

 1.2. Create Service Key

After service creation we click “view instance”.
There, we press on “Create Service Key”.

createXsuaa1.jpg

 We can enter any name of our choice, e.g. "myKey".
Press Create.

1.3. View Credentials

After creating the service key, we can view the credentials, i.e. the content of the service key.
We can either use the “View Credentials” button on the service details, or the context button of the new service key.

createXsuaa2.jpg

The content of the service key is a JSON object which contains 3 relevant properties:

🔸clientid
🔸clientsecret
🔸url

createXsuaa3.jpg

We should take a note of them.
Why?
This is the OAuth client, with its name and password, and the URL from where it can fetch an access token.
We need this information to configure both AEM and CPI. 

2. AEM: Configure OAuth Authentication

Now we head over to AEM for defining the configurations required for OAuth authentication.

Why?
Our iFlow will establish a connection 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 validate the token content.
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.0. Enable OAuth Authentication

We login to our SAP Integration Suite, advanced event mesh.
We 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.

AEM_auth.jpg

 

This step needs to be executed only once.

2.1. Create OAuth Profile

In the Cluster Manager, we choose our broker and 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 "xsuaaForAem".
After pressing Create we can configure this new profile.

Note:
One profile corresponds to one OAuth client.
In our case, the OAuth client is the service instance of XSUAA, but it could be an “Application” in IAS or 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 sb-na-a8e2450d-3c00...

🔸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 0WUSE1jLm...
Note:
The client secret is required for AEM to call the introspection endpoint of XSUAA.

🔸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.

🔸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 url of XSUAA, which is our issuer and is contained in the JWT.
We copy the url property from chapter 1.3
In my example:
https://subdomain.authentication.eu12.hana.ondemand.com 

🔸Discovery Endpoint
It is not required in our scenario.
Optionally you can enter a URL like this:
https://subdomain.authentication.eu12.hana.ondemand.com/.well-known/openid-configuration 

🔸JWKS Endpoint
It is not required in our scenario
Also, it is not required if the Discovery Endpoint is provided, because the JWKS Endpoint can be found in the metadata that are returned by the discovery endpoint.
Anyways, in my example, the URL would be
https://subdomain.authentication.eu12.hana.ondemand.com/token_keys 

Alternatively, the JWKS endpoint can be found when looking into a JWT token.
The JWT token contains a header which contains a claim called jku.
This is an abbreviation for JWKS Url and the value is the same as above.

What is JWKS?
It stands for JSON Web Key Set.
It is a JSON object which contains a list of keys.
These keys are public keys, exposed by the Authorization Server.
A public key is used to verify a signature.
It is required, because a JWT token is signed (with private key) by the Authorization Server and the signature is contained in the third segment of the JWT.
Thus, the receiver of the JWT token can validate the token by extracting the signature and verifying it with the public key that is found via the first segment of the JWT
In our example, we don’t need to enter the value, because the value can be read from the JWT token

🔸Introspection Endpoint
This is an endpoint which is offered by the Authorization Server (XSUAA).
We compose the URL by appending /introspect to the url property from chapter 1.3.
In my example:
https://subdomain.authentication.eu12.hana.ondemand.com/introspect 
Docu can be found in the Cloud Foundry UAA reference
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.

🔸Validate Access Token Audience
We enable the setting and enter the value of client ID into the field.
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 enter the clientid which we received in chapter 1.3

🔸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 our example, it is the token endpoint of XSUAA server, the value which we will need in chapter 3.1
We enter the value of the url property of chapter 1.3
However, that’s only the base URL, so we have to append the endpoint segments: /oauth/token

In my example:
https://subdomain.authentication.eu12.hana.ondemand.com/oauth/token 

🔸Validate Access Token Scope 
We disable this validation, because we don’t require a specific scope.

🔸Validate Access Token Type
We can enable this validation and leave the default values as:
at+jwt (accept access tokens and JWT tokens)

AEM_oauthprofile.jpg

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

2.2. 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.

AEM_selectProfile.jpg

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

2.3. 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 3 steps:

Broker Service
🔹enable OAuth Authentication
Broker Manager
🔹create OAuth Profile
🔹define default OAuth Profile

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.3.
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 "xsuaaForAem".

🔸Token Service URL
This is the endpoint provided by the Authorization Server, used for requesting a JWT token.
We enter the value of the url property of chapter 1.3.
However, that’s only the base URL, so we have to append the endpoint segments: /oauth/token
The full URL in my example:
https://subdomain.authentication.eu12.hana.ondemand.com/oauth/token

🔸Client ID
Here we enter the value of the clientid property which we copied in chapter 1.3.
In my example, I enter "sb-na-a8e2450d-3c00"

🔸Client Secret
Here we enter the clientsecret property which we copied in chapter 1.3.
In my example, I enter "0WUSE1jLmsX/BcB0LlD"

🔸Client Authentication
We choose “Send as Body Parameter”.

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

cpi_credentials.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 go to
AEM dashboard -> Cluster Manager -> Choose service -> “Connect” tab
We expand “Solace Messaging” and copy Secured SMF Host Public Internet URL.

aem_adapter_host.jpg

 We paste the clipboard content into the “Host” field in AEM adapter.
Message VPN
Same procedure: copy the “Message VPN” value from the “Connect” tab of AEM.
See screenshot above.
Paste the clipboard content into the “Message VPN” field of the AEM-adapter in iFlow.
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: "xsuaaForAem".

aem_adapter_conn.jpg

 🔸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”.

aen_adapter_xsuaa_clicre2.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:

result1.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.

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.
Super
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 XSUAA 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

🌟