cancel
Showing results for 
Search instead for 
Did you mean: 

Passing Dynamic Oauth Token & API Key in Header of Sender REST Adapter

Binod_Thakur
Participant
0 Kudos

Hi All,

I'm configuring sender REST Pooling to consume Ariba API. I'm passing two value 1st temporary oauth token and 2nd API Key in header filed, it's working fine. API Key is constant but token is getting expire in every 27 minutes.

I have written java code to fetch token dynamically and passing it in DynamicConfiguration, but don't know where to put access_token variable in REST Adapter.

DynamicConfiguration conf = input.getDynamicConfiguration(); DynamicConfigurationKey keyHeader1 = DynamicConfigurationKey.create("http://sap.com/xi/XI/System", "HeaderFieldOne"); conf.put(keyHeader1, "Bearer "+access_token);

Please guide me with two thing

1. Java mapping code to generate token (i have written, but need sample code to understand better)

2. How to configure token variable in sender REST adapter.

ADAPTER CONFIGURATION:-

When i select REST in Message Protocol, XI Dynamic Attribute is coming but HTTP Header tab is not there, where i will mention

Authorization Bearer {access_token}?

Appreciate your time,

Binod Kumar

peter_wallner2
Active Contributor
0 Kudos

In your general tab you did not configure OAuth. That is confusing to me. Token handling can be done by the adapter itself, no java code needed. Look at the last screenshot in this thread: https://answers.sap.com/questions/651899/rest-polling-oauth-20-token-401-error.html I hope that helps.

Binod_Thakur
Participant
0 Kudos

Hi Peter,

Thanks for your response.

I am using PO 7.40, in this Oauth option is very different compare to PO 7.50

When i select Authorize with Oauth

And after selecting the SAML Bearer Assertion, below options are coming.

I do not know what value need to provide here.

Regards,

Binod Kumar

Accepted Solutions (0)

Answers (12)

Answers (12)

Muniyappan
Active Contributor

Since you need the token in the sender channel, it will not be possible with UDF or java mapping to achieve this requirement.

Basically you need create custom adapter module, which will generate and store the token in the dynamic variable.

Please check this blog for adding dynamic config variable. You have to perform look up in the adapter module and then add it to dynamic config.

https://blogs.sap.com/2016/08/23/setting-dynamic-configuration-attributes-using-custom-adapter-modul...

Binod_Thakur
Participant
0 Kudos

Hi Muniyappan,

Thanks for your response.

I have to use both side sender & receiver rest adapter.

Are we sure that to authenticate sender rest polling dynamically we have only one option "custom adapter module" ? Is there any other option for it ? Why UDF/java mapping is not possible in sender rest adapter?

sugata.bagchi2 has mentioned in above comment that he has created the Lookup to generate the token and set it to header, let him to respond.

----

I want to authenticate rest adapter at receiver side as well, I saw one thread that they have mention we can do it by java mapping also.

https://answers.sap.com/questions/386648/rest-adapter-dynamic-token-authentication.html

One thing I'm not getting "write the token to the header of the TransformationOutput"

how to do it, can you please help me on this ?


Thanks again,

Binod

0 Kudos

I would like to find how to add a Rest Sender to the audience of the JWT Token, to be able to give authorization.

I'm working on that, if I find the solution I'll share it with you 🙂

anil_peddi
Discoverer
0 Kudos

Hi Sebastian,

Any solution on REST POLLING Sender Side Configuration?

0 Kudos

Hi, binod1991s did you find the solution?

I'm having the same scenario, REST Sender with JWT.

Regards,

Sebastian

Binod_Thakur
Participant

Hi Sebastian,

I didn't find the solution and later it got canceled by client, if I will get anything will update on this thread.

anil_peddi
Discoverer
0 Kudos

Hi Binod,

Any solution on REST POLLING Sender Side Configuration.

sugata_bagchi2
Active Contributor
0 Kudos

Hi Binod,

As Muniyappan said you have to deal this with module at sender channel. I agree with him, because you can call UDF/ java mapping once the message is in PI. But in your case you want to populate the header as soon as the message ID created in PI.
In this case, PI will Poll the Rest end point and as soon as a message is fetched it will execute the adapter module to add the header.

Thanks

Sugata

Binod_Thakur
Participant

Hi Sugata & Muniyappa,

Thanks for your response.

So, we are confirm now sender side we have only one option that is development of "adapter module bean" ?

Please confirm this, i will update further on this thread.

Regards,

Binod


vicky20691
Active Contributor
0 Kudos

Hi,

For receiver side, you can do it now out of the box
https://blogs.sap.com/2019/04/25/fetch-oauth-token-in-rest-is-now-out-of-the-box/

For sender side i still do not understand.. Basically SAP PO is generating API which you are exposing and testing from postman, so it means postman or any one calling SAP PO REST api must get a token from SAP PO am i right ?
In that case it has to be done at system level where SAP PO system allows calls to it's end point using token

Regards,

Vikas

Muniyappan
Active Contributor
0 Kudos

could you please share you channel config? what is the name being used in the channel?

Muniyappan
Active Contributor
0 Kudos

receiver side you can use java map/udf/custom adapter module.

But in the sender, it is not the case. sender interface has get the payload, then only mapping/udf will come into picture. Hence you can not use udf/mapping here.

Binod_Thakur
Participant
0 Kudos

Okay.

For receiver rest adapter, below code is to send token dynamically to header.
I have taken from existing working interface.

public String CaptureToken(String input, Container container)throws StreamTransformationException {
DynamicConfiguration conf = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
if (conf != null) {
   DynamicConfigurationKey key = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/REST", "XHeaderName1");
   conf.put(key, input);
		}
return input;
}
----------
Note: Here input is token value that is coming from previous UDF.
When I implement same code in java mapping to send token dynamically, it was not taking token, Unauthorized.
Can you please check whether same code can be used in java mapping or not ?
I am writing below code in java mapping
------------------------
private static final DynamicConfigurationKey keyHeader1 = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/REST", "XHeaderName1");
DynamicConfiguration conf = arg0.getDynamicConfiguration();
conf.put(keyHeader1, access_token);
-------------------------

Is above code is correct or do i have to modify something ?


Regards,
Binod

Binod_Thakur
Participant
0 Kudos

Hello Sugata,

Need one more help, after this i will close this thread.

Actually above requirement got canceled but got new similar kind of requirement.

I have tested from postman and PO Development environment, it's working fine.

I don't know how to pass the access token to the header dynamically, I am using sender REST Pooling to fetch the data from REST based API.

I have written java mapping code also

public static String GenerateAccessToken() {


		String AuthURL = "https://<host_name>/auth";
		try {


			URL url = new URL(AuthURL);
			URLConnection connection = url.openConnection();
			HttpURLConnection httpConn = (HttpURLConnection) connection;


			// Set Header
			httpConn.setRequestProperty("Content-Type", "application/json");
			httpConn.setRequestProperty("Accept", "application/json");
			httpConn.setDoOutput(true);
			httpConn.setDoInput(true);
			httpConn.setRequestMethod("POST");


			// Set Body
			String credential = "{\"username\":\"<api_user_name>\",\"password\":\"<api-password>\"}";


			OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
			writer.write(credential);
			writer.close();


			BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
			StringBuffer jsonString = new StringBuffer();
			String line;
			while ((line = br.readLine()) != null) {
				jsonString.append(line);
			}
			br.close();


			System.out.println(jsonString);
			String access_token = jsonString.substring(10,jsonString.indexOf("\",\"expiration\":\""));


			return access_token.toString();
			


		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}


		// { 
                //    "token":"access_token",
                //      "expiration":"2019-04-23 08:39:01.000+0000"
                // }


	}



Here I need to pass the username and password in body and Content-Type and Accept as a application/json value to generate the access token.

Can you please guide me which one i have to used UDF/LookUP. I don't know which value have to pass in header of Sender REST Pooling adapter.

 When i see in your UDF


//return token;

token = "access_token="+token;
DynamicConfiguration dynConf = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION); 

DynamicConfigurationKey key = DynamicConfigurationKey.create( "http://sap.com/xi/XI/System/REST", "access_token"); 
dynConf.put(key, token); return ""

Which value need to provide in Header that will fetch token dynamically ?
Since two variable is here "access_token" and "token" if we will pass token variable then what is use of access_token variable ? I am little confuse ..


NOTE: Please help me with UDF/Lookup and explain me in detail, i am not familiar with UDF/Lookup

I have one more question why we can't use java mapping here ?
below is my logic to send token dynamically

-------------
	private static final DynamicConfigurationKey keyHeader1 = DynamicConfigurationKey.create("http://sap.com/xi/XI/System/REST", "XHeaderName1");
conf.put(keyHeader1, access_token);
--------------------
but it's throwing error ...


Please help me ...

Regards,
Binod
sugata_bagchi2
Active Contributor
0 Kudos

Hi Binod,

You can create a OData service in your SAP gateway to call Ariba to get the data in SAP and from there you can also trigger a scenario - proxy to jdbc.

Thanks

Sugata

sugata_bagchi2
Active Contributor
0 Kudos

I have created a UDF to do REST lookup to get the token and maintained that in header

here is the code -

String token = "";
StringBuffer sb = new StringBuffer();
String party = ""; // emtpy values cannot be passed from Directory to the mapping parameters.
Channel RESTchannel = LookupService.getChannel(party,service,channel); // parameter for component and channel from mapping in ICO
SystemAccessor accessor = LookupService.getSystemAccessor(RESTchannel);
getTrace().addInfo("Parameters for Token Lookup - Service: "+service+", Channel: "+channel);
try{
InputStream inputStream;
String reqString = "{ \"grant_type\": \"client_credentials\" }";
getTrace().addInfo("Request: "+reqString);
inputStream = (InputStream) new ByteArrayInputStream(reqString.getBytes());
com.sap.aii.mapping.lookup.Payload payload = LookupService.getXmlPayload(inputStream);
com.sap.aii.mapping.lookup.Payload result = accessor.call(payload);
byte[] b = new byte[4096];
for (int n; (n = result.getContent().read(b)) != -1;){
sb.append(new String(b,0,n));
}
getTrace().addDebugMessage("Response: "+sb);
String resp = sb.toString();
// Response handling code below depends on the response structure you are receiving
// Below is the sample response JSON
/*
{
"access_token": "3927f9ac7928bf91de26c5c93d0974dd1d9c88a7",
"expires_in": 3600,
"token_type": "Bearer",
"scope": null
}
*/
resp = resp.replace("{","");
resp = resp.replace("}","");
String [] respArr = resp.split(",");
for (int i = 0;i<respArr.length;i++)
{
if (respArr[i].startsWith("\"access_token\""))
{
int p = respArr[i].indexOf(":");
token = respArr[i].substring(p+1);
token = token.replace("\"","");

}
}
getTrace().addInfo("Token: "+token);

}
catch (Exception e){
e.printStackTrace();
}
finally
{

if (accessor!=null) accessor.close();
}
//return token;
token = "access_token="+token; // Parameter replace in REST URL tab in the actual receiver REST channel
DynamicConfiguration dynConf = (DynamicConfiguration) container.getTransformationParameters().get(StreamTransformationConstants.DYNAMIC_CONFIGURATION);
DynamicConfigurationKey key = DynamicConfigurationKey.create( "http://sap.com/xi/XI/System/REST", "access_token"); dynConf.put(key, token);
return ""

Binod_Thakur
Participant
0 Kudos

Yeah, I was not able to find where we need to put access_token variable in sender Rest adapter.

1. For sender Rest adapter UDF is fine and in receiver we can go for java mapping & UDF is that correct ?

2. Can you please provide brief details on how to use UDF for dynamic token with complete code? and where you're passing following details

client_id

client_secret

3. Recently i came across receiver rest adapter project, i have developed standalone complete java application for that, i was not able to complete by rest adapter, PI7.40

Let me explain you the scenario :

1. In 1st call we will get token

2. in 2nd call with the help of token, it generates ChunkURI

3. In 3rd call, have to make post call on ChunkURI along with passing the file

I tested through postman, it was working fine but through PI OMG so much horrible

-> PI 7.40 is not able to handle token automatic

-> any how i passed the token in header

-> created the ChunkURI as well

-> but last step i sucked, i created the java code for file attachment but there were no option to put dynamic variable

If you could provide any solution for it, it would be great.

----------------------------

Related to REST adapter basic question still i have

1. what is better solution to handle dynamic token in sender & receiver side as well ??



Lot's of thanks for your support,

Binod

former_member186472
Participant
0 Kudos

Hi Sugata, we are trying to get access_token from Azure AD, we followed same UDF that is mentioned in your response. But we see only below first string from response. Not able to see other tags from response object. Appreciate your input.

  • respArr[i]-->><token_type>Bearer</token_type>
sugata_bagchi2
Active Contributor
0 Kudos

Hello Binod,

How do you invoke the java map if you want the token at sender side? not sure if an adapter module can be invoked (I tink not possible too as it requires message as Object).

could you please elabborate your scenario?

Thanks

Sugata

Binod_Thakur
Participant
0 Kudos

My scenario is REST to JDBC

I have to call Ariba API through rest adapter and using jdbc have to post it.

bhalchandraswcg
Contributor
0 Kudos
Binod_Thakur
Participant
0 Kudos

Thanks Bhalchandra for your response, I'm not configuring in receiver rest adapter, I'm configuring in sender rest adapter.

I have written java mapping to fetch token dynamically but where to pass the variable in sender side?

Using 7.40, just help me with how to handle dynamic token in sender rest adapter

Regards,

Binod