Skip to content
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ ScribeJava support out-of-box several HTTP clients:
* Microsoft Live (https://login.live.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/LiveExample.java)
* Misfit (http://misfit.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/MisfitExample.java)
* NAVER (http://www.naver.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/NaverExample.java)
* NetSuite (https://www.netsuite.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/NetSuiteExample.java)
* Odnoklassniki Одноклассники (http://ok.ru/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/OdnoklassnikiExample.java)
* Polar (https://www.polar.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/PolarAPIExample.java)
* Pinterest (https://www.pinterest.com/) [example](https://github.com/scribejava/scribejava/blob/master/scribejava-apis/src/test/java/com/github/scribejava/apis/examples/PinterestExample.java)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.github.scribejava.apis;

import com.github.scribejava.core.builder.api.DefaultApi10a;
import com.github.scribejava.core.services.HMACSha256SignatureService;
import com.github.scribejava.core.services.SignatureService;

public class NetSuiteApi extends DefaultApi10a {

protected NetSuiteApi() {
}

private static class InstanceHolder {
private static final NetSuiteApi INSTANCE = new NetSuiteApi();
}

public static NetSuiteApi instance() {
return InstanceHolder.INSTANCE;
}

@Override
public SignatureService getSignatureService() {
return new HMACSha256SignatureService();
}

@Override
public String getAccessTokenEndpoint() {
return null;
}

@Override
public String getRequestTokenEndpoint() {
return null;
}

@Override
public String getAuthorizationBaseUrl() {
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package com.github.scribejava.apis.examples;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.scribejava.apis.NetSuiteApi;
import com.github.scribejava.core.builder.ServiceBuilder;
import com.github.scribejava.core.model.OAuth1AccessToken;
import com.github.scribejava.core.model.OAuthRequest;
import com.github.scribejava.core.model.Response;
import com.github.scribejava.core.model.Verb;
import com.github.scribejava.core.oauth.OAuth10aService;
import org.apache.http.client.utils.URIBuilder;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;

public class NetSuiteExample {
private static final ObjectMapper jsonMapper = new ObjectMapper();

// Replace these with your own account id, consumer key, consumer secret, token id, token secret and restlet domain
private static final String ACCOUNT_ID = "your_account_id";
private static final String CONSUMER_KEY = "your_consumer_key";
private static final String CONSUMER_SECRET = "your_consumer_secret";
private static final String TOKEN_ID = "your_token_id";
private static final String TOKEN_SECRET = "your_token_secret";
private static final String RESTLET_DOMAIN = "YOUR-ACCOUNT-ID.restlets.api.netsuite.com";

private static final String RESTLET_PATH = "/app/site/hosting/restlet.nl";
private static final String SCRIPT = "script";
private static final String DEPLOY = "deploy";
private static final String PROTECTED_RESOURCE_URL = new URIBuilder()
.setScheme("https")
.setHost(RESTLET_DOMAIN)
.setPath(RESTLET_PATH)
.addParameter(SCRIPT, "your_restlet_script_id")
.addParameter(DEPLOY, "your_restlet_deploy_id")
.toString();

private NetSuiteExample() {
}

@SuppressWarnings("PMD.SystemPrintln")
public static void main(String... args) throws IOException, InterruptedException, ExecutionException {
final OAuth10aService service = new ServiceBuilder(CONSUMER_KEY)
.apiSecret(CONSUMER_SECRET)
.build(NetSuiteApi.instance());

System.out.println("=== NetSuite's OAuth (Token-based Authorization) ===");
System.out.println();

final OAuth1AccessToken accessToken = new OAuth1AccessToken(TOKEN_ID, TOKEN_SECRET);

// Now let's go and ask for a protected resource!
System.out.println("Now we're going to access a protected resource...");
final OAuthRequest request = new OAuthRequest(Verb.POST, PROTECTED_RESOURCE_URL);
request.setRealm(ACCOUNT_ID);
service.signRequest(accessToken, request);
request.addHeader("Content-Type", "application/json");

Map<String, String> requestMap = new HashMap<>();
requestMap.put("message", "your request body for POST and PUT");
String jsonRequestBody = jsonMapper.writer().writeValueAsString(requestMap);
request.setPayload(jsonRequestBody);

System.out.println("Request body to send:");
System.out.println(jsonRequestBody);
System.out.println();

try (Response response = service.execute(request)) {
System.out.println("Got it! Let's see what we found...");
System.out.println();
System.out.println(response.getCode());
System.out.println(response.getBody());
}

System.out.println();
System.out.println("That's it man! Go and build something awesome with ScribeJava! :)");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.github.scribejava.core.services;

import com.github.scribejava.core.base64.Base64;
import com.github.scribejava.core.exceptions.OAuthSignatureException;
import com.github.scribejava.core.utils.OAuthEncoder;
import com.github.scribejava.core.utils.Preconditions;

import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

/**
* HMAC-SHA256 implementation of {@link SignatureService}
*/
public class HMACSha256SignatureService implements SignatureService {

private static final String EMPTY_STRING = "";
private static final String CARRIAGE_RETURN = "\r\n";
private static final String HMAC_SHA256 = "HmacSHA256";
private static final String METHOD = "HMAC-SHA256";

/**
* {@inheritDoc}
*/
@Override
public String getSignature(String baseString, String apiSecret, String tokenSecret) {
try {
Preconditions.checkEmptyString(baseString, "Base string can't be null or empty string");
Preconditions.checkNotNull(apiSecret, "Api secret can't be null");
return doSign(baseString, OAuthEncoder.encode(apiSecret) + '&' + OAuthEncoder.encode(tokenSecret));
} catch (NoSuchAlgorithmException | InvalidKeyException | RuntimeException e) {
throw new OAuthSignatureException(baseString, e);
}
}

private String doSign(String toSign, String keyString) throws NoSuchAlgorithmException, InvalidKeyException {
final SecretKeySpec key = new SecretKeySpec(keyString.getBytes(StandardCharsets.UTF_8), HMAC_SHA256);
final Mac mac = Mac.getInstance(HMAC_SHA256);
mac.init(key);
final byte[] bytes = mac.doFinal(toSign.getBytes(StandardCharsets.UTF_8));
return Base64.encode(bytes).replace(CARRIAGE_RETURN, EMPTY_STRING);
}

/**
* {@inheritDoc}
*/
@Override
public String getSignatureMethod() {
return METHOD;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.github.scribejava.core.services;

import com.github.scribejava.core.exceptions.OAuthException;
import org.junit.Before;
import org.junit.Test;
import org.junit.function.ThrowingRunnable;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;

public class HMACSha256SignatureServiceTest {

private HMACSha256SignatureService service;

@Before
public void setUp() {
service = new HMACSha256SignatureService();
}

@Test
public void shouldReturnSignatureMethodString() {
final String expected = "HMAC-SHA256";
assertEquals(expected, service.getSignatureMethod());
}

@Test
public void shouldReturnSignature() {
final String apiSecret = "apiSecret";
final String tokenSecret = "tokenSecret";
final String baseString = "baseString";
final String signature = "xDJIQbKJTwGumZFvSG1V3ctym2tz6kD8fKGWPr5ImPU=";
assertEquals(signature, service.getSignature(baseString, apiSecret, tokenSecret));
}

@Test
public void shouldThrowExceptionIfBaseStringIsNull() {
assertThrows(OAuthException.class, new ThrowingRunnable() {
@Override
public void run() {
service.getSignature(null, "apiSecret", "tokenSecret");
}
});
}

@Test
public void shouldThrowExceptionIfBaseStringIsEmpty() {
assertThrows(OAuthException.class, new ThrowingRunnable() {
@Override
public void run() {
service.getSignature(" ", "apiSecret", "tokenSecret");
}
});
}

@Test
public void shouldThrowExceptionIfApiSecretIsNull() {
assertThrows(OAuthException.class, new ThrowingRunnable() {
@Override
public void run() {
service.getSignature("baseString", null, "tokenSecret");
}
});
}

@Test
public void shouldNotThrowExceptionIfApiSecretIsEmpty() {
final String apiSecret = " ";
final String tokenSecret = "tokenSecret";
final String baseString = "baseString";
final String signature = "VRZvKmNIgbjfwPOoCPEvxFUV23v0BopcE6OE9P2Odz0=";
assertEquals(signature, service.getSignature(baseString, apiSecret, tokenSecret));
}
}