Personal Insights
Get SharePoint AccessToken using SAP PI UDF
Parent blog Integrate SharePoint using SAP PI
Overview:
SharePoint supports OAuth to authorize the application request instead of credentials (username and password) while calling SharePoint-REST to perform CRUD operations.
Open Authorization (OAuth) is an open protocol for authorization. OAuth enables secure authorization from desktop and web applications in a simple and standard way. It lets users approve an application to act on their behalf without sharing their user name and password.
To perform any Read/Write operation using respective SharePoint-REST service, first we require “SharePoint Access token” for authentication.
To fetch “SharePoint Access token” following REST-details can be used:
- REST-URL: https://accounts.accesscontrol.windows.net/<tenantID>/tokens/OAuth/2
- Method: POST
- Headers: Content-Type: “application/x-www-form-urlencoded”
- Body: (Request Parameter format)
- grant_type=client_credentials
&client_id=<shp_clientId>@<shp_tenantId>
&client_secret=<shp_clientSecret>
&resource=00000003-0000-0ff1-ce00-000000000000/<org_Shp_Host>@<shp_tenantId>
- grant_type=client_credentials
- Note: Following details are specific to Organization’s SharePoint data:
- <shp_clientId>: Client ID is a GUID for the SharePoint Add in
- <shp_tenantId>: Tenant ID is SharePoint Online Site Realm
- <shp_clientSecret>: Client Secret is the password for the add-ins.
- <org_Shp_Host>: Organisation’s SharePoint host name
SAP PI UDF example to fetch SharePoint Access Token:
Java Imports required in UDF are as :
- java.net.URL
java.net.URLConnection
java.net.HttpURLConnection
Java Input parameters:
Java UDF Code:
public String getShpToken(String shp_clientId, String shp_tenantId, String shp_clientSecret, String shp_clientDomain, Container container) throws StreamTransformationException{
/**
* This function helps to get SharePoint Access Token. SharePoint Access
* Token is required to authenticate SharePoint REST service while performing Read/Write events.
* SharePoint REST-URL to get access token is as:
* https://accounts.accesscontrol.windows.net/<tenantID>/tokens/OAuth/2
*
* Input required related to SharePoint are as:
* 1. shp_clientId
* 2. shp_tenantId
* 3. shp_clientSecret
*/
String accessToken = "";
try {
// AccessToken url
String wsURL = "https://accounts.accesscontrol.windows.net/" + shp_tenantId + "/tokens/OAuth/2";
URL url = new URL(wsURL);
URLConnection connection = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) connection;
// Set header
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
// Prepare RequestData
String jsonParam = "grant_type=client_credentials"
+ "&client_id=" + shp_clientId + "@" + shp_tenantId
+ "&client_secret=" + shp_clientSecret
+ "&resource=00000003-0000-0ff1-ce00-000000000000/<org_Shp_Host>@" + shp_tenantId;
//Here, <org_Shp_Host> is "Origanisations's Sharepoint Host"
// Send Request
DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream());
wr.writeBytes(jsonParam);
wr.flush();
wr.close();
// Read the response.
InputStreamReader isr = null;
if (httpConn.getResponseCode() == 200) {
isr = new InputStreamReader(httpConn.getInputStream());
} else {
isr = new InputStreamReader(httpConn.getErrorStream());
}
BufferedReader in = new BufferedReader(isr);
String responseString = "";
String outputString = "";
// Write response to a String.
while ((responseString = in.readLine()) != null) {
outputString = outputString + responseString;
}
// Extracting accessToken from string, here response (outputString)is a Json format string
if (outputString.indexOf("access_token\":\"") > -1) {
int i1 = outputString.indexOf("access_token\":\"");
String str1 = outputString.substring(i1 + 15);
int i2 = str1.indexOf("\"}");
String str2 = str1.substring(0, i2);
accessToken = str2;
}
} catch (Exception e) {
accessToken = "Error: " + e.getMessage();
}
return accessToken;
}
Testing Screen of UDF inside Graphical Map:
Note:
Before, consuming SharePoint-APIs, we should always check its behavior using standard tools like ‘POSTMAN’ etc, to avoid unnecessary confusion (like in case if error occurs due to UDF code or Service credentials).
TEST using POSTMAN Tool:
Set Header:
Set-Body: Method-01 | We can set token request in BODY part as below:
Set-Body: Method-02 | We can set token request like below too:
Here, If we get Error “AADSTS7000215: Invalid client secret is provided”
Then Root-Cause is, that, Client_secret had “few unnecessary characters like + and /”
And Resolution is to encoded Client_Secret. The encoded client_secret you can get from original using any online Encode/Decode-String tool/Link.
Hi Dilip,
OAuth 2.0 authentication for REST services can be done directly now in CC itself by selecting OAuth 2.0 Grants Type Flow in PI 7.5.
You can check below blog -
https://blogs.sap.com/2017/07/21/sap-po-rest-integration-with-salesforce-oauth/
Thanks,
Apu
Hello Dilip Kumar Krishnadev Pandey
Your valuable thoughts on this please.
https://answers.sap.com/questions/12872081/how-to-read-and-write-oauh-access-token.html
Thanks in advance!
Hi Dilip,
Using your above java code i have tried to get the access token from share point but getting an error i.e. but when i am trying with postman its giving proper response using the same access key and other credentials .I am attaching the code and the postman screenshot for your response.
{"error":"invalid_client","error_description":"AADSTS7000215: Invalid client secret is provided.\r\nTrace ID: 6a71613e-4dea-464b-8141-28fef1fd9100\r\nCorrelation ID: 4e54ec74-63b1-4fbc-89e0-63e7f17dc519\r\nTimestamp: 2020-06-19 20:04:28Z","error_codes":[7000215],"timestamp":"2020-06-19 20:04:28Z","trace_id":"6a71613e-4dea-464b-8141-28fef1fd9100","correlation_id":"4e54ec74-63b1-4fbc-89e0-63e7f17dc519","error_uri":"https://accounts.accesscontrol.windows.net/error?code=7000215"}
Java Code:
####################
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
public class SharepointAccessClass {
/**
* upload a file to a sharepoint library
*/
public static void main(String[] args) throws Exception{
/**
* This function helps to get SharePoint Access Token. SharePoint Access
* Token is required to authenticate SharePoint REST service while performing Read/Write events.
* SharePoint REST-URL to get access token is as:
* https://accounts.accesscontrol.windows.net/<tenantID>/tokens/OAuth/2
*
* Input required related to SharePoint are as:
* 1. shp_clientId
* 2. shp_tenantId
* 3. shp_clientSecret
*/
String accessToken = "";
String shp_clientId="f83e1c66-f64d-49a1-85e2-207e47092918";
String shp_tenantId="42150afd-062a-4a0f-81b9-0323526054cc";
String shp_clientSecret="28t3QzULzpYlhJhHqt8BTGn+xY/WmQQcokb1SxKryNI=";
try {
// AccessToken url
String wsURL = "https://accounts.accesscontrol.windows.net/" + shp_tenantId + "/tokens/OAuth/2";
URL url = new URL(wsURL);
URLConnection connection = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) connection;
// Set header
httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
httpConn.setRequestProperty("Content-Length", "0");
httpConn.setRequestProperty("Host", "<calculated when request is sent>");
httpConn.setDoOutput(true);
httpConn.setDoInput(true);
httpConn.setRequestMethod("POST");
// Prepare RequestData
String jsonParam = "grant_type=client_credentials"
+ "&client_id=" + shp_clientId + "@" + shp_tenantId
+ "&client_secret=" + shp_clientSecret
+ "&resource=00000003-0000-0ff1-ce00-000000000000/naveedtest.sharepoint.com@" + shp_tenantId;
//Here, <org_Shp_Host> is "Origanisations's Sharepoint Host"
// Send Request
DataOutputStream wr = new DataOutputStream(httpConn.getOutputStream());
wr.writeBytes(jsonParam);
wr.flush();
wr.close();
// Read the response.
InputStreamReader isr = null;
if (httpConn.getResponseCode() == 200) {
isr = new InputStreamReader(httpConn.getInputStream());
} else {
isr = new InputStreamReader(httpConn.getErrorStream());
}
BufferedReader in = new BufferedReader(isr);
String responseString = "";
String outputString = "";
// Write response to a String.
while ((responseString = in.readLine()) != null) {
outputString = outputString + responseString;
System.out.println(outputString);
}
// Extracting accessToken from string, here response (outputString)is a Json format string
if (outputString.indexOf("access_token\":\"") > -1) {
int i1 = outputString.indexOf("access_token\":\"");
String str1 = outputString.substring(i1 + 15);
int i2 = str1.indexOf("\"}");
String str2 = str1.substring(0, i2);
accessToken = str2;
}
} catch (Exception e) {
accessToken = "Error: " + e.getMessage();
}
}
}
Thanks in Advance.
Cheers,
Uddeshya
Hi Uddeshya,
Sorry for late response.
Thanks & Regards,
Dilip P.
Hi Team,
I have a similar requirement, but token(QAuthorization) is passed in Response Header as shown below instead of payload, How to retrieve token from header.
Can this be achieved using UDF ?
Json Request
Thanks,
Varun
Hi Varun,
Sorry for late response, by now you may have manged this.
As per your case, using JavaPgm, I would be reading the ResponseHeader to get oAuthorizationToken.
Thanks & Regards,
Dilip P.
Hi
When I do testing in Mapping, I am getting empty result.
Any idea what could I be missing?
I just modified url and request data as per my request.
Hi Amarnath,
Sorry, for late reply, I hope by now, you may have already addressed the issue.
SharePoint has given dedicated URI and it's protocol for each supported action, that can be followed. And in case of error, plz focus on type of error code returned from API
Thanks & Regards,
Dilip
Excellent post Dilip, you're a life saver
I know Java but not PI
Got my access token UDF working
Not sure how to plug it in to do the report calls
But at least I know PJ can handle the various types of API calls
Well done
Hi Doug,
Good to hear your input.
Just for information, you can use JavaMap, where you can club AccessToken call and next data-POST API.
I had a requirement, where I was having 10K+ data from source application and I had to POST them into SharePoint in File-Format having 200 records per file. So, I had used JavaMap
You can refere below JavaMap code examples:
https://blogs.sap.com/2018/08/26/post-pdf-file-in-sharepoint-using-sap-pi-java-map/
https://blogs.sap.com/2017/11/29/sharepoint-bulk-insert-using-java-program/
Thanks & Regards,
Dilip