How to set OAuth realm in RestAssured - java

I am using RestAssured library for automating NetSuite Restlets. This Restlets are using OAuth 1.0 for authentication. Apart from consumer key, consumer secret, access token and token secret, I need to set advanced fields like REALM. But I couldn't find any way to set that in RestAssured.
RequestSpecification request = new RequestSpecBuilder()
.addHeader("Content-Type", ContentType.JSON.toString())
.setBaseUri(url).build()
.auth().oauth(
netsuiteConfig.getNetsuiteConsumerKey(),
netsuiteConfig.getNetsuiteConsumerSecret(),
netsuiteConfig.getNetsuiteTokenId(),
netsuiteConfig.getNetsuiteTokenSecret()
);
Here is the api call using Postman

RestAssured does not support this. Create OAuth 1.0 string using some library (I have used com.github.seratch:signedrequest4j) and set Authorization header in RestAssured RequestSpecification.
OAuthConsumer consumer = new OAuthConsumer(consumerKey, consumerSecret);
OAuthAccessToken accessToken = new OAuthAccessToken(tokenId, tokenSecret);
OAuthRealm realm = new OAuthRealm(myRealm);
SignedRequest request =
SignedRequestFactory.create(realm, consumer, accessToken);
request.readQueryStringAndAddToSignatureBaseString(url);
request.setHeader("Content-Type", "application/json");
String oAuthNonce = String.valueOf((new SecureRandom()).nextLong());
Long oAuthTimestamp = System.currentTimeMillis() / 1000L;
String signature = request.getSignature(url,
HttpMethod.POST, oAuthNonce, oAuthTimestamp);
String authorizationHeader = request
.getAuthorizationHeader(signature, oAuthNonce, oAuthTimestamp);

I was using the library mentioned in the previous answer but then I realised I needed to use PATCH requests which wasn't supported.
I started using the google oauth client instead and after days of trying, finally got this example working:
val signer = OAuthHmacSigner()
signer.clientSharedSecret = CONSUMER_SECRET
signer.tokenSharedSecret = TOKEN_SECRET
val oauthParameters = OAuthParameters()
oauthParameters.consumerKey = CONSUMER_KEY
oauthParameters.token = ACCESS_TOKEN
oauthParameters.signer = signer
val genericUrl = GenericUrl("https://{ACC_ID}.suitetalk.api.netsuite.com/path/to/endpoint")
oauthParameters.version = "1.0"
oauthParameters.computeNonce()
oauthParameters.computeTimestamp()
oauthParameters.computeSignature("GET", genericUrl)
oauthParameters.realm = REALM
val authHeader = oauthParameters.authorizationHeader
RestAssured.with()
.log().all()
.header("Authorization", authHeader)
.urlEncodingEnabled(false)
.request(Method.GET, genericUrl.toString())
.then()
.statusCode(200)
urlEncoding is set to false for urls with query params that are already encoded. For example:
{url}/invoice?q=internalid%20IS%2012
I hope it helps someone in the future!

Related

Not authorized to access scope - Amazon Advertising API

My purpose is to download the advertising report using existing application details such as AMAZON_CLIENT_ID, AMAZON_CLIENT_SECRET & Access tokens to other java application.
I was able to get the new access token using AMAZON_CLIENT_ID, AMAZON_CLIENT_SECRET & refresh_token. Below is the code to fetch a new access token.
OkHttpClient client = new OkHttpClient();
Response response;
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "grant_type=refresh_token&refresh_token=" + refreshToken + "&client_id=" + amzClientId + "&client_secret=" + amzClientSceret);
Request request = new Request.Builder()
.url(“https://api.amazon.com/auth/o2/token”)
.post(body)
.addHeader("content-type", "application/x-www-form-urlencoded")
.build();
response = client.newCall(request).execute();
After sending the api request to fetch the campaign level stats data, is gives the following error
{"code":"UNAUTHORIZED","
details":"Not authorized to access scope XXXXXXXXXXXXXXXXXX","
requestId":"xxxxxxxxxxxxx"}"
My question here is, Can I use the same existing AMAZON_CLIENT_ID, AMAZON_CLIENT_SECRET & Access tokens to fetch stats to different java applications(without using login with amazon)?
Any help would be appreciated. Thank you!!
You need to include the access token and client ID for subsequent requests.
.addHeader("Authorization", "Bearer " + access_token)
.addHeader("Amazon-Advertising-API-ClientId", client_id)

How to add parameter in request URL( Java 11)?

I'm absolute beginner in java. Trying to send some http request using the built in java httpclient.
How can I add the request parameters into the URI in such format:
parameter = hi
url = "https://www.url.com?parameter=hi"
With the code, I'm using, I can only set the headers but not the request parameters
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create(url))
.GET()
.build();
var reponse = client.send(request, HttpResponse.BodyHandlers.ofString());
return reponse.body();
Thank you very much!
With native Java 11, it has to be done like you did. You need to add the parameters within the url parameter already. Or you need to create your own builder that allows you to append parameter.
However, your requested behaviour is possible if you make use of libraries. One way to do it is to make use of Apache URIBuilder
var client = HttpClient.newHttpClient();
URI uri = new URIBuilder(httpGet.getURI())
.addParameter("parameter", "hi")
.build();
var request = HttpRequest.newBuilder(uri)
.GET()
.build();
var reponse = client.send(request, HttpResponse.BodyHandlers.ofString());
return reponse.body();
You don't have methods for adding parameters, but you can use String.format() to format the URL nicely.
final static String URL_FORMAT = "http://url.com?%s=%s";
final String request = String.format(URL_FORMAT, "paramater", "hi");

Can't use Dynamics CRM token (401 Unauthorized)

I'm writing a simple android app in Java and recently implemented retrieving a token for a user from Microsoft Dynamics CRM (I have created a connected app in Azure, got application id, secret etc).
I want other users of this application to be able to connect to their CRMs and organizations.
Now I'm trying to use the token with the REST API and getting 401 error.
Read all the related answers here, nothing helped. The code I'm using:
//retrieved the authorization code by this url:
mAuthorizationUrl = Configuration.AUTHORIZE_ENDPOINT + "?response_type=code&client_id="
+ Configuration.CLIENT_ID + "&redirect_uri=" + Configuration.REDIRECT_URI;
...
//Retrieving access_token:
String body_content = "grant_type=authorization_code&client_id=" +
Configuration.CLIENT_ID + "&redirect_uri=" + Configuration.REDIRECT_URI
+ "&code=" + code + "&resource=" + Configuration.CLIENT_ID;
//I don't have app URI (resource) in Azure, so I used app id (client id).
//This worked (see above).
RequestBody body = RequestBody.create(
MediaType.parse("application/x-www-form-urlencoded; charset=utf-8"),
body_content);
Request request = new Request.Builder()
.url(Configuration.TOKEN_RETRIEVAL_ENDPOINT)
.post(body)
.build();
Response response = new OkHttpClient().newCall(request).execute();
String responseString = response.body().string();
JSONObject json = new JSONObject(responseString);
String token = json.getString("access_token");
//NOT WORKING CODE:
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
.protocols(Collections.singletonList(Protocol.HTTP_1_1))
.build();
Map<String, String> headers = new ArrayMap<>();
headers.put("Authorization", "Bearer " + token));
headers.put("Accept", "application/json");
request = new Request.Builder()
.url(Configuration.REST_ENDPOINT)
.headers(Headers.of(headers))
.build();
try {
response = okHttpClient
.newCall(request)
.execute();
statusCode = response.code();
}
...
//401 UNAUTHORIZED
Endpoints I used:
AUTHORIZE_ENDPOINT = https://login.microsoftonline.com/common/oauth2/authorize
TOKEN_RETRIEVAL_ENDPOINT = https://login.microsoftonline.com/common/oauth2/token
REST_ENDPOINT = url_to_crm/api/data/v9.0/
Here are two sample Java projects that connect and authenticate with the Dynamics Web API via Azure:
Link 1
Link 2
Hope this helps.

Google API Java GET request with body content

My Goal is to request GoogleTaskAPI for TASKLIST with specified no.of result.
It works fine, If I m passing no requestBody. But I need to pass request parameter to specific number of results to be returned. When I do that, it creates new Tasklist, Instead of listing. So how to do this?
My Code:
GoogleAccessProtectedResource access = new GoogleAccessProtectedResource(accessToken, httpTransport, jsonFactory, clientId, clientSecret, refreshToken);
HttpRequestFactory rf = httpTransport.createRequestFactory(access);
String endPointUrl = "https://www.googleapis.com/tasks/v1/users/#me/lists";
String requestBody = "{\"maxResults\":3}";
GenericUrl endPoint = new GenericUrl(endPointUrl);
ByteArrayContent content = new ByteArrayContent("application/json", requestBody.getBytes());
//Try 0: Works, But Retrieving all of my Tasklist, I need only 3
//HttpRequest request = rf.buildGetRequest(endPoint);
//-------
//Try 1: Fails to retrieve
//HttpRequest request = rf.buildGetRequest(endPoint);
//request.setContent(content);
//request.getContent().writeTo(System.out);
//-------
//Try 2: Fails to retrieve
HttpRequest request = rf.buildRequest(HttpMethod.GET, endPoint, content);
request.getContent().writeTo(System.out);
//-------
HttpResponse response = request.execute();
String str = response.parseAsString();
utils.log(str);
maxResults is a query parameter, not a request parameter, so you can just put it in the url:
String endPointUrl = "https://www.googleapis.com/tasks/v1/users/#me/lists?maxResults=3";
You should also consider using the Java client's Tasks interface for making requests; it may be a little easier since it handles the details of the url for you:
http://code.google.com/p/google-api-java-client/wiki/APIs#Tasks_API

Twitter API status update always returns "Incorrect signature"

I'm using Signpost as OAuth implementation for posting to Twitter. And implemented the GoogleAppEngineOAuthConsumer and GoogleAppEngineOAuthProvider classes, but since they're pretty trivial, so I'm not providing their sources here (yet).
Here's my authentication part, which seems to work just fine.
LoginServlet.java:
// fetching the request token
OAuthConsumer consumer = new GoogleAppEngineOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
OAuthProvider provider = new GoogleAppEngineOAuthProvider(REQUEST_TOKEN_URL, ACCESS_TOKEN_URL, AUTHORIZATION_URL);
String redirectUrl = provider.retrieveRequestToken(consumer, CALLBACK_URL);
// cache the request token and request token secret
response.sendRedirect(redirectUrl);
CallbackServlet.java
// fetching the access token
String verifier = (String) req.getParameter("oauth_verifier");
// retrieve request token and request token secret from cache
OAuthConsumer consumer = new GoogleAppEngineOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
OAuthProvider provider = new GoogleAppEngineOAuthProvider(REQUEST_TOKEN_URL,
consumer.setTokenWithSecret(token, tokenSecret);
provider.setOAuth10a(true);
provider.retrieveAccessToken(consumer, verifier);
// store access token and access token secret
And here's the actual problematic part.
TweetServlet.java
OAuthConsumer consumer = new GoogleAppEngineOAuthConsumer(CONSUMER_KEY, CONSUMER_SECRET);
// retrieve access token and access token secret from storage
consumer.setTokenWithSecret(accessToken, accessTokenSecret);
final HTTPRequest updateStatus = new HTTPRequest(new URL("http://api.twitter.com/1/statuses/update.json"), HTTPMethod.POST);
updateStatus.setPayload(("status=" + URLEncoder.encode(message, "UTF-8")).getBytes());
consumer.sign(updateStatus);
logger.debug(new String(URLFetchServiceFactory.getURLFetchService().fetch(updateStatus).getContent()));
Each and every time it results: {"request":"/1/statuses/update.json","error":"Incorrect signature"}.
I was able to solve this by myself. The problem was that I wasn't setting a Content-Type header to the request, so the signing didn't sign the parameters and it resulted the invalid signature. Once I set it to application/x-www-form-urlencoded it started working.
final HTTPRequest updateStatus = new HTTPRequest(new URL("http://api.twitter.com/1/statuses/update.json"), HTTPMethod.POST);
updateStatus.addHeader(new HTTPHeader("Content-Type", "application/x-www-form-urlencoded"));

Categories

Resources