RestEasy client to secured service - java

We have deployed RestEasy services, as part of application, and secured them with filter (a class that implements javax.servlet.Filter). Filter checks if object of the User class exists in the session. The user object is inserted into session when user logs in. Everything works fine.
However, we need to create standalone app that accesses these services. We decided to use RestEasy client API. We can access these services if the filter is turned off, but how do we perform this logging in and session manipulation from RestEasy client API.

Let's assume your standalone client was written in Java.
Then a sample code would look like this.
First we need to authenticate the user by calling your auth service and obtain a valid session ID. Let's assume the obtained session id is equivalent to "f47cdba8-d066-48e8-ad29-8c4222906bc7". Then we can call the REST service with the valid session ID as a HTTP header parameter.
String url = "http://localhost:8081/AuthService/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// optional default is GET
con.setRequestMethod("GET");
//add request header
con.setRequestProperty("User-Agent", USER_AGENT);
con.setRequestProperty("Authorization", "token=f47cdba8-d066-48e8-ad29-8c4222906bc7");
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
At the back end you need to process this HTTP header parameter based Session ID and validate the oncoming request before serving it.
Hope this helps.

Related

Authorization issue when reading sheet

I want to read a table from Google Sheets from my android application.
I want to do that by Google Sheets APIs.
I declared the sheet as public, created API key and tried to send the GET service call:
https://sheets.googleapis.com/v4/spreadsheets/{My Sheet key}/values/responses:append?key={My API credential key}
I get 401 code.
Response:
Request is missing required authentication credential. Expected OAuth
2 access token, login cookie or other valid authentication credential.
See
https://developers.google.com/identity/sign-in/web/devconsole-project.
My code:
private static final String SHEET_URL = "https://sheets.googleapis.com/v4/spreadsheets/1d534sQ5xaNbr65wMM_qH2yjXo3EPrrp3o34z-Foledg/values/responses:append?key=AIzaSyDT88Nq6jhtaKH-vIVEuvGO1d9Sx8ewR0w";
public String GetConanimList() throws Exception {
URL url = new URL(SHEET_URL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("GET");
conn.setRequestProperty("Content-Type", "application/json");
OutputStream os = conn.getOutputStream();
String jsonPayload = null;
//os.write(jsonPayload.getBytes());
os.flush();
os.close();
int statusCode = conn.getResponseCode();
System.out.println("Response from WA Gateway: \n");
System.out.println("Status Code: " + statusCode);
BufferedReader br = new BufferedReader(new InputStreamReader(
(statusCode == 200) ? conn.getInputStream() : conn.getErrorStream()
));
String output;
String response = "";
while ((output = br.readLine()) != null) {
response = response + output;
}
conn.disconnect();
return response;
}
What am I missing? Thanks.
To use Google Sheets API, you need to authorize your requests.
There are two ways to identify your application: using an OAuth 2.0
token (which also authorizes the request) and/or using the
application's API key. Here's how to determine which of those
options to use:
If the request requires authorization (such as a request for an individual's private data), then the application must provide an OAuth 2.0 token with the request. The application may also provide the API key, but it doesn't have to.
If the request doesn't require authorization (such as a request for public data), then the application must provide either the API key or an OAuth 2.0 token, or both—whatever option is most convenient for you.
You can also refer to the quickstart projects available as a guide on how to correctly implement this.

Java HTTPS (SSL) Connection Return 400 Status where as CURL/ARC works for same URL

I'm trying to connect to salesforce production account via OAuth and exchange an access token by giving a refresh token.
When i make a call using Chrome Advanced Rest Client or CURL i'm able to get the access token; but when i'm trying to make the same call using java HttpClient or URLConnection i'm getting a 400 status.
String url = "https://login.salesforce.com/services/oauth2/token";
String requestBody = "grant_type=refresh_token&client_id=myClientId&client_secret=myClientSecret&refresh_token=myRefreshToken";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add reuqest header
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "myapp/1.0");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(requestBody);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + requestBody);
System.out.println("Response Code : " + responseCode);
BufferedReader br = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = br.readLine()) != null) {
response.append(inputLine);
}
br.close();
//print result
System.out.println(response.toString());
I examined both requests using wireshark. And both the requests look identical. Since the URL is https, i posted the request to a dummy URL and verified using wireshark.
Anybody ran into this kinda of issue ? BTW the same code works for developer edition and is not working for production edition. And for production edition it works with CURL and Chrome ARC.
Salesforce only allows HTTPS connections on TLS 1.1 or higher. Since i'm running on Java 7, default is TLS 1.0. As a result the request is failing from Java.
By adding the following property we can add support for TLSv1.1 and TLSv1.2
-Dhttps.protocols=TLSv1.1,TLSv1.2

Authentication requests using HTTPS to an API in Java

I am looking to use an API called HookTheory. I am making the HTTPS calls in Java, and since its my first time using HTTP or HTTPS clients I am running into a few road blocks.
Here are the document's details on User Authentication:
You authenticate to the Hooktheory API by providing an HTTP Bearer Token, according to the OAuth 2 protocol. Your HTTP Bearer Token is retrieved through the API with your www.hooktheory.com username and password. To retrieve your HTTP Bearer Token, make the following request:
POST users/auth
The body of the request must contain your www.hooktheory.com username and password:
{
"username": "Hooktheory",
"password": "0123456789"
}
The response will contain three fields, as shown below:
{
"id": 1234,
"username": "Hooktheory",
"activkey": "aoa6jjacz34kcta3aomeqwuz89"
}
The "activkey" property contains your HTTP Bearer Token; include it as an authorization header in all future requests to the API.
Can someone explain in better detail how I would go about doing this in Java?
My starter code is the following:
String url = "https://api.hooktheory.com/v1/users/auth";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add request header
con.setRequestMethod("POST");
con.setRequestProperty("username", username);
con.setRequestProperty("password", password);
String urlParameters = "sn=C02G8416DRJM&cn=&locale=&caller=&num=12345";
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
System.out.println("\nSending 'POST' request to URL : " + url);
System.out.println("Post parameters : " + urlParameters);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
//print result
System.out.println(response.toString());
This code is basically a copy of the code here.
I get a 401 error (authentication) when I run the post code above. I'm guessing its because I haven't formatted the get/post requests correctly.
Can somebody point me in the right direction?
You've set username and password as request properties, which are HTTP headers. Per the HookTheory docs, you need to send these on the request body.
Specifically, you need to send the JSON request on the body like this:
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
String requestBody = String.format("{ \"username\": \"%s\", \"password\": \"%s\" }", username, password);
wr.writeBytes(requestBody);
Also, per their docs you should indicate that this is JSON by setting the Accept and Content-Type headers. This is done prior to sending the post request data through calls like this:
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Content-Type", "application/json");
So the entire block looks like:
String url = "https://api.hooktheory.com/v1/users/auth";
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Content-Type", "application/json");
// Send post request
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
String requestBody = String.format("{ \"username\": \"%s\", \"password\": \"%s\" }", username, password);
wr.writeBytes(requestBody);
wr.flush();
wr.close();
code 401 clearly specifies something wrong with authentication. stack trace shows unauthenticated on server side.
10.4.2 401 Unauthorized
The request requires user authentication. The response MUST include a WWW-Authenticate header field (section 14.47) containing a challenge applicable to the requested resource. The client MAY repeat the request with a suitable Authorization header field (section 14.8). If the request already included Authorization credentials, then the 401 response indicates that authorization has been refused for those credentials. If the 401 response contains the same challenge as the prior response, and the user agent has already attempted authentication at least once, then the user SHOULD be presented the entity that was given in the response, since that entity might include relevant diagnostic information. HTTP access authentication is explained in "HTTP Authentication: Basic and Digest Access Authentication"

Paypal update invoice rest api HTTP response code: 500

i am currently trying to use REST api provided by Paypal to create my own service using servlet. I manage to transfer the cURL code into HttpsURLConnection using java.
Here is my code:
JSONObject returnJson = new JSONObject();
PrintWriter out = response.getWriter();
JSONParser jparser = new JSONParser();
try{
String inputStr = request.getParameter("input");
System.out.println(inputStr);
JSONObject inputJson = (JSONObject) jparser.parse(inputStr);
String accessToken = (String) inputJson.get("access_token");
String invoiceId = (String) inputJson.get("invoiceId");
String url = "https://api.sandbox.paypal.com/v1/invoicing/invoices/"+invoiceId;
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
//add reuqest header
con.setRequestMethod("PUT");
con.setRequestProperty("Accept-Language", "text/html; charset=UTF-8");
con.setRequestProperty("Content-Type", "application/json");
con.setRequestProperty("Authorization", "Bearer "+accessToken);
//Tentatively, the input is hard coded, after integration, the input comes from http request.
//However, only merchant email in mandatory for invoice creation in sand box so far
//For details of invoice attributes please refer to this link--> https://developer.paypal.com/docs/api/#update-an-invoice
String urlJsonString = "{\"id\":\""+invoiceId+"\",\"status\":\"DRAFT\",\"merchant_info\":{\"email\":\"rui.song.2013-facilitator#sis.smu.edu.sg\",\"first_name\":\"Dennis\",\"last_name\":\"Doctor\",\"business_name\":\"MedicalProfessionals,LLC\",\"phone\":{\"country_code\":\"US\",\"national_number\":\"5032141716\"},\"address\":{\"line1\":\"1234MainSt.\",\"city\":\"Portland\",\"state\":\"LALA\",\"postal_code\":\"97217\",\"country_code\":\"US\"}},\"billing_info\":[{\"email\":\"sally-patient#example.com\"}],\"shipping_info\":{\"first_name\":\"Sally\",\"last_name\":\"Patient\",\"business_name\":\"Notapplicable\",\"address\":{\"line1\":\"1234BroadSt.\",\"city\":\"Portland\",\"state\":\"LALA\",\"postal_code\":\"97216\",\"country_code\":\"US\"}},\"items\":[{\"name\":\"Sutures\",\"quantity\":100,\"unit_price\":{\"currency\":\"USD\",\"value\":\"250\"}}],\"invoice_date\":\"2014-01-07PST\",\"payment_term\":{\"term_type\":\"NO_DUE_DATE\"},\"tax_calculated_after_discount\":false,\"tax_inclusive\":false,\"note\":\"MedicalInvoice16Jul,2013PST\",\"total_amount\":{\"currency\":\"USD\",\"value\":\"250\"}}";
System.out.println(urlJsonString);
con.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(con.getOutputStream());
wr.write(urlJsonString);
wr.close();
int responseCode = con.getResponseCode();
System.out.println("Response Code : " + responseCode);
out.print(responseCode);
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer res= new StringBuffer();
while ((inputLine = in.readLine()) != null) {
res.append(inputLine);
}
in.close();
returnJson = (JSONObject) jparser.parse(res.toString());
System.out.println(returnJson);
}catch(Exception e){
e.printStackTrace();
returnJson.put("message", e);
}
out.print(returnJson);
I am testing the service on localhost, and i will manually pass in TWO parameters: "access_token" and "invoiceId" like this:
http://localhost:8080/Authentication/PaypalUpdateInvoiceServlet?input={"access_token":"A015Rv3XNo4fmFh4JC2sJiGjl1oEQ5w-B9azU.H6nlzMm1s","invoiceId":"INV2-9TRP-2S2R-OPBD-XK9T"}
These two pieces of info are obtained by me using the similar code i mentioned above.
I only modified codes in the entier HttpsURLConnection part to correspond with the cURL request and response sample provided in Paypal site. Link -->(https://developer.paypal.com/docs/api/#update-an-invoice)
Thus far, i successfully implement Create, Retrieve for invoice. I use the same way to make the servlet call with the specific parameters required and are able to get the expected response show on Paypal site.
BUT Now i am stuck with update invoice. When i make the servlet call.
i will receive:
500{"message":java.io.IOException: Server returned HTTP response code: 500 for URL: https://api.sandbox.paypal.com/v1/invoicing/invoices/IINV2-9TRP-2S2R-OPBD-XK9T}
Can anyone help me explain why i get this error and how shall i fix this?

Servlet request to another servlet with authorization

I have tomcat server with some applications. This server uses standart j_secure_check auth. On another tomcat server I need to deploy application that must be some proxy to first server. So I need to invoke servlet from another servlet but first I need to do authentication with j_secure_check. Is it possible to do it programmely?
You need to grab the session cookie and pass it through on subsequent requests.
String url = "http://example.com/j_security_check?j_username=foo&j_password=bar";
HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
if (connection.getResponseCode() == 200) { // 200 = OK, 401 = unauthorized
String cookie = connection.getHeaderField("Set-Cookie").split(";", 2)[0];
url = "http://example.com/somepage.jsp";
connection = (HttpURLConnection) new URL(url).openConnection();
connection.setRequestProperty("Cookie", cookie);
InputStream input = connection.getInputStream();
// You can now write it to response.getOutputStream().
}

Categories