package com.sap.jam.api.sample;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import com.sap.jam.oauth.client.HttpMethod;
import com.sap.jam.oauth.client.OAuthClientHelper;
import com.sap.jam.oauth.client.Pair;
import com.sap.jam.oauth.client.SignatureMethod;
/**
* This class provides some working Java sample client code to illustrate authentication of the SAP Jam API
* with OAuth1.0 and the HMAC-SHA1 signature type.
*
* This example assumes a Jam deployment with an OAuth client application configured for a company,
* and a user that can successfully log into the company via the Web UI to authorize the OAuth client to make
* API requests on behalf of the user.
*
* It is run by invoking the "main" method.
* There are 3 command line arguments: <baseUrl> <consumerKey> <consumerSecret>
* For example: https://integration3.sapjam.com Ywkxz2QhRQiTBhAJihFW OUaMDZOxmRC1s0i23e3R00y0zoag1WEtN6WJuB7w
*
* Depending on the environment, a proxy can be configured using VM arguments supplied to the jvm. For example,
* for the environment where this program was developed these are:
* -Dhttp.proxyHost=proxy.van.sap.corp
* -Dhttp.proxyPort=8080
* -Dhttps.proxyHost=proxy.van.sap.corp
* -Dhttps.proxyPort=8080
*
*/
public class OAuth1aHmacSha1WorkflowSample {
public static void main (String[] args) throws Exception {
if (args.length != 3) {
System.out.println("Command line arguments: <baseUrl> <consumerKey> <consumerSecret>");
System.out.println("For example: https://integration3.sapjam.com Ywkxz2QhRQiTBhAJihFW OUaMDZOxmRC1s0i23e3R00y0zoag1WEtN6WJuB7w");
System.exit(1);
}
System.out.println("Proxy settings:");
System.out.println("http.proxyHost="+System.getProperty("http.proxyHost"));
System.out.println("http.proxyPort="+System.getProperty("http.proxyPort"));
System.out.println("https.proxyHost="+System.getProperty("https.proxyHost"));
System.out.println("https.proxyPort="+System.getProperty("https.proxyPort"));
String baseUrl = args[0];
String consumerKey = args[1];
String consumerSecret = args[2];
runOAuth1aFlows(baseUrl, consumerKey, consumerSecret);
}
private static void runOAuth1aFlows(String baseUrl, String consumerKey, String consumerSecret) throws Exception {
System.out.println("\n***************************************************************");
DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss Z");
Date date = new Date();
System.out.println("SAP Jam OAuth1a flows run: " + dateFormat.format(date));
Pair<String, String> requestTokenPair = postOAuth1aRequestToken(baseUrl, consumerKey, consumerSecret);
String requestToken = requestTokenPair.fst();
String requestTokenSecret = requestTokenPair.snd();
String verifier = authorizeRequestToken(baseUrl, requestToken);
Pair<String, String> accessTokenPair = postOAuth1aAccessToken(baseUrl, consumerKey, consumerSecret, requestToken, requestTokenSecret, verifier);
String accessToken = accessTokenPair.fst();
String accessTokenSecret = accessTokenPair.snd();
getCurrentUser(baseUrl, consumerKey, consumerSecret, accessToken, accessTokenSecret);
postOAuth1aRevokeAccessToken(baseUrl, consumerKey, consumerSecret, accessToken, accessTokenSecret);
//after the access token is revoked, calling an API with it will result in an authentication error
getCurrentUser(baseUrl, consumerKey, consumerSecret, accessToken, accessTokenSecret);
}
/**
* Creates the OAuth1.0 request token
* POST /oauth/request_token
*/
private static Pair<String,String> postOAuth1aRequestToken(String baseUrl, String consumerKey, String consumerSecret) throws Exception {
System.out.println("\n***************************************************************");
String urlString = baseUrl + "/oauth/request_token";
System.out.println("POST " + urlString);
OAuthClientHelper och = new OAuthClientHelper();
och.setHttpMethod(HttpMethod.POST);
och.setRequestUrl(new URL(urlString));
och.setConsumerKey(consumerKey);
och.setConsumerSecret(consumerSecret);
//must set either a callback URL or indicate that the callback is out of band
och.setOutOfBandCallback();
och.setSignatureMethod(SignatureMethod.HMAC_SHA1);
StringBuilder result = new StringBuilder();
HttpURLConnection connection = createConnection(och.getRequestUrl());
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String authorizationHeader = och.generateAuthorizationHeader ();
connection.setRequestProperty("Authorization", authorizationHeader);
System.out.println("Authorization: " + authorizationHeader);
int responseCode = connection.getResponseCode();
System.out.println("HTTP response code: " + responseCode);
InputStream is;
if (connection.getResponseCode() >= 400) {
is = connection.getErrorStream();
} else {
is = connection.getInputStream();
}
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result.append(inputLine);
}
in.close();
String resultString = result.toString();
System.out.println("Response body: " + resultString);
String[] tokenAndSecret = resultString.split("&");
String requestToken = tokenAndSecret[0].split("=")[1];
String requestTokenSecret = tokenAndSecret[1].split("=")[1];
System.out.println("requestToken: " + requestToken);
System.out.println("requestTokenSecret: " + requestTokenSecret);
return new Pair<String, String>(requestToken, requestTokenSecret);
}
private static String authorizeRequestToken(String baseUrl, String requestToken) throws Exception {
System.out.println("\n***************************************************************");
System.out.println("Paste the following link into your browser: " + baseUrl + "/oauth/authorize?oauth_token=" + requestToken);
System.out.println("Authorize the token, then enter the verification token here: ");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String verifier = br.readLine().trim();
System.out.println("verifier: " + verifier);
return verifier;
}
/**
* Creates the OAuth1.0 access token from a request token and verifier
* POST /oauth/access_token
*/
private static Pair<String, String> postOAuth1aAccessToken(String baseUrl, String consumerKey, String consumerSecret, String requestToken, String requestTokenSecret, String verifier) throws Exception {
System.out.println("\n***************************************************************");
String urlString = baseUrl + "/oauth/access_token";
System.out.println("POST " + urlString);
OAuthClientHelper och = new OAuthClientHelper();
och.setHttpMethod(HttpMethod.POST);
och.setRequestUrl(new URL(urlString));
och.setConsumerKey(consumerKey);
och.setConsumerSecret(consumerSecret);
och.setToken(requestToken);
och.setTokenSecret(requestTokenSecret);
och.setVerifier(verifier);
och.setOutOfBandCallback();
och.setSignatureMethod(SignatureMethod.HMAC_SHA1);
StringBuilder result = new StringBuilder();
HttpURLConnection connection = createConnection(och.getRequestUrl());
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String authorizationHeader = och.generateAuthorizationHeader ();
connection.setRequestProperty("Authorization", authorizationHeader);
System.out.println("Authorization: " + authorizationHeader);
int responseCode = connection.getResponseCode();
System.out.println("HTTP response code: " + responseCode);
InputStream is;
if (connection.getResponseCode() >= 400) {
is = connection.getErrorStream();
} else {
is = connection.getInputStream();
}
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result.append(inputLine);
}
in.close();
String resultString = result.toString();
System.out.println ("Response body: " + resultString);
String[] tokenAndSecret = resultString.split("&");
String accessToken = tokenAndSecret[0].split("=")[1];
String accessTokenSecret = tokenAndSecret[1].split("=")[1];
System.out.println("accessToken: " + accessToken);
System.out.println("accessTokenSecret: " + accessTokenSecret);
return new Pair<String, String>(accessToken, accessTokenSecret);
}
/**
* Revokes the access token so that it cannot be used for further API calls.
* POST /oauth/revoke_token
*/
private static void postOAuth1aRevokeAccessToken(String baseUrl, String consumerKey, String consumerSecret, String accessToken, String accessTokenSecret) throws Exception {
System.out.println("\n***************************************************************");
String urlString = baseUrl + "/oauth/revoke_token";
System.out.println("POST " + urlString);
OAuthClientHelper och = new OAuthClientHelper();
och.setHttpMethod(HttpMethod.POST);
och.setRequestUrl(new URL(urlString));
och.setConsumerKey(consumerKey);
och.setConsumerSecret(consumerSecret);
och.setToken(accessToken);
och.setTokenSecret(accessTokenSecret);
och.setSignatureMethod(SignatureMethod.HMAC_SHA1);
StringBuilder result = new StringBuilder();
HttpURLConnection connection = createConnection(och.getRequestUrl());
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
String authorizationHeader = och.generateAuthorizationHeader ();
connection.setRequestProperty("Authorization", authorizationHeader);
System.out.println("Authorization: " + authorizationHeader);
int responseCode = connection.getResponseCode();
System.out.println("HTTP response code: " + responseCode);
InputStream is;
if (connection.getResponseCode() >= 400) {
is = connection.getErrorStream();
} else {
is = connection.getInputStream();
}
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result.append(inputLine);
}
in.close();
String resultString = result.toString();
System.out.println ("Response body: " + resultString);
}
/**
* Calls the GET /api/v1/OData/Self endpoint using OAuth 1.0 with HMAC-SHA1 requesting a JSON response.
* This endpoint provides information about the current user.
*/
private static String getCurrentUser(String baseUrl, String consumerKey, String consumerSecret, String accessToken, String accessTokenSecret) throws Exception {
System.out.println("\n***************************************************************");
String urlString = baseUrl + "/api/v1/OData/Self";
System.out.println("GET " + urlString);
OAuthClientHelper och = new OAuthClientHelper();
och.setHttpMethod(HttpMethod.GET);
och.setRequestUrl(new URL(urlString));
och.setConsumerKey(consumerKey);
och.setConsumerSecret(consumerSecret);
och.setToken(accessToken);
och.setTokenSecret(accessTokenSecret);
och.setSignatureMethod(SignatureMethod.HMAC_SHA1);
StringBuilder result = new StringBuilder();
HttpURLConnection connection = createConnection(och.getRequestUrl());
connection.setRequestMethod("GET");
String authorizationHeader = och.generateAuthorizationHeader ();
connection.setRequestProperty("Authorization", authorizationHeader);
System.out.println("Authorization: " + authorizationHeader);
connection.setRequestProperty("Accept", "application/json");
int responseCode = connection.getResponseCode();
System.out.println("HTTP response code: " + responseCode);
InputStream is;
if (connection.getResponseCode() >= 400) {
is = connection.getErrorStream();
} else {
is = connection.getInputStream();
}
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
while ((inputLine = in.readLine()) != null) {
result.append(inputLine);
}
in.close();
String resultString = result.toString();
System.out.println ("Response body: " + resultString);
return resultString;
}
private static class DefaultTrustManager implements X509TrustManager {
@Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
@Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {}
@Override
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
private static HttpURLConnection createConnection(URL requestUrl) throws Exception {
HttpURLConnection connection;
if (requestUrl.getProtocol().equals("https")) {
//http://stackoverflow.com/questions/1828775/httpclient-and-ssl
//Nice trick (for non-production code) to create a SSL Context that accepts any cert.
//This lets us avoid configuring any self-signed certificate from a test system.
SSLContext ctx = SSLContext.getInstance("TLS");
ctx.init(new KeyManager[0], new TrustManager[] {new DefaultTrustManager()}, new SecureRandom());
SSLContext.setDefault(ctx);
connection = (HttpsURLConnection)requestUrl.openConnection();
((HttpsURLConnection )connection).setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String arg0, SSLSession arg1) {
return true;
}
});
} else {
connection = (HttpURLConnection)requestUrl.openConnection();
}
return connection;
}
}