How to invoke Google Drive REST API with Jersey? - java

I am trying to use Java Jersey instead of Google client libraries to access the Google File API, but I keep getting returned a response status of "401 Unauthorized". Prior to invoking the call, I have obtained an access token from Google, using Oauth:
public static String getGoogleFileResource(final String fileId,
final String accessToken) {
//projection
ClientConfig cc = new DefaultClientConfig();
cc.getProperties().put(ClientConfig.PROPERTY_FOLLOW_REDIRECTS, true);
Client client = Client.create(cc);
String url = String
.format("https://www.googleapis.com/drive/v2/files/%s?fields=downloadUrl&key=%s",
fileId, GoogleClientConstants.GOOGLE_api_key);
WebResource webResource = client.resource(url);
String response = webResource
.accept(MediaType.APPLICATION_JSON_TYPE,
MediaType.APPLICATION_XML_TYPE)
.header("Authorization", "Bearer " + accessToken)
.get(String.class);
logger.info("Authorization - " + "Bearer " + accessToken);
logger.info(" reponse " + response);
return response;
}
What am I doing wrong ?

Turns out you need to add your access token to the http request header.
In the Google developer's guide: "uploading a file"
https://developers.google.com/drive/manage-uploads
You need to send a post request like this:
POST /upload/drive/v2/files?uploadType=media HTTP/1.1
Host: www.googleapis.com
Content-Type: image/jpeg
Content-Length: number_of_bytes_in_JPEG_file
Authorization: your_auth_token
JPEG data
note that in the header you need to put a your_auth_token

Related

Basic Authentication for JAVA Application using OkHttp

First I wanted to authenticate my java application using OkHttp and then after authentication the response returns a session ID(key) that I wanted to use in subsequent API calls. below is the code that I am using to achieve this.
String url = "my application url";
String username = "xxx";
String password = "zzz";
String userpass = username + ":" + password;
String basicAuth = "Basic :" + new String(Base64.getEncoder().encode(userpass.getBytes()));
OkHttpClient client = new OkHttpClient();
Response response ;
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", basicAuth)
.build();
response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
but its throwing an error saying
{"responseStatus":"FAILURE","responseMessage":"Request method 'GET' not supported","errorCodes":null,"errors":[{"type":"METHOD_NOT_SUPPORTED","message":"Request method 'GET' not supported"}],"errorType":"GENERAL"}
can someone please help me to solve this. or if any have any other idea to authenticate a java application using okhttp then please suggest...
You should use the helper classes to avoid most of the logic for username and password.
https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/Authenticate.java
String credential = Credentials.basic("jesse", "password1");
return response.request().newBuilder()
.header("Authorization", credential)
.build();
Assuming this API is POST and not GET also follow
https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/PostString.java
Request request = new Request.Builder()
.url("https://api.github.com/markdown/raw")
.post(RequestBody.create(postBody, MEDIA_TYPE_MARKDOWN))
.build();
You had it all right already. Just a small fix needed:
String basicAuth = "Basic " + new String(Base64.getEncoder().encode(userpass.getBytes()));
i.e you just need to remove extra ':' as it's already taken care of in .addHeader("Authorization", basicAuth) part.

AWS Chime: How to sign an HTTP Request for Create Meeting API in spring boot?

I didn't find any useful way to generate the Signature V4 in java for signing an AWS Chime HttpRequest. I want to use 3 apis of Aws Chime (Create meeting, create attendee and delete meeting) inside my java code.
Can anyone help me please !
API Details:
Url: https://service.chime.aws.amazon.com/meetings
Body: { "ClientRequestToken": "AXEXAMPLE", "MediaRegion":
"us-east-2" }
Headers: "content-type", "application/json" "host",
"service.chime.aws.amazon.com" "x-amz-date", "20200526T094404Z"
"authorization", ?(Generated Signature)
API Key: JHDCHGEXAEXAMPLE Secret Key : 4sjfkkjffs/sfkkh/sfkj/example
private Response createMeeting() {
OkHttpClient client = new OkHttpClient();
Response response = null;
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\n\t\"ClientRequestToken\": \"AXEXAMPLE\",\n \"MediaRegion\": \"us-east-2\"\n}");
Request request = new Request.Builder()
.url("https://service.chime.aws.amazon.com/meetings")
.post(body)
.addHeader("content-type", "application/json")
.addHeader("host", "service.chime.aws.amazon.com")
.addHeader("content-length", "68")
.addHeader("x-amz-date", getIsoDate())
.addHeader("authorization", "?????????") //To be replaced by generated signature
.addHeader("cache-control", "no-cache")
.build();
try {
response = client.newCall(request).execute();
System.out.println("ResponseMessage===========> " + response.message());
} catch (IOException e) {
System.out.println("Error===========> " + e.getMessage());
}
return response;
}
The error I am getting is: The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.

When sending okhttp request: HTTP ERROR 405 and invalid_client

I'm making a request to a website. However, I keep getting a returned JSON of {"error":"invalid_client"}. Additionally, when I navigate to the URL I'm making the request to through a web browser it shows HTTP ERROR 405.
From what I read on those errors that might mean that my request isn't structured correctly.
According to the API's documentation, this is an example of the request type I'm trying to do:
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "client_secret={your_client_secret}&client_id={your_client_id}&code={your_authorization_code}&grant_type=authorization_code&redirect_uri={your_redirect_uri}");
Request request = new Request.Builder()
.url("https://api.website.com/v2/oauth2/token")
.post(body)
.addHeader("content-type", "application/x-www-form-urlencoded")
.addHeader("cache-control", "no-cache")
.build();
Response response = client.newCall(request).execute();
From what I can tell mine should be doing the same thing, just a little differently.
Here is a Pastebin of my doInBackground method (I'm using AsynchTask). Here is the more applicable part:
OkHttpClient client = new OkHttpClient();
// A section here gets strings from a JSON file storing values such as client_id
RequestBody bodyBuilder = new FormBody.Builder()
.add("client_secret", CLIENT_SECRET)
.add("client_id", CLIENT_ID)
.add("code", AUTHORIZATION_CODE)
.add("grant_type", GRANT_TYPE)
.add("redirect_uri", REDIRECT_URI)
.build();
System.out.println("Built body: " + bodyBuilder.toString());
String mediaTypeString = "application/x-www-form-urlencoded";
MediaType mediaType = MediaType.parse(mediaTypeString);
RequestBody body = RequestBody.create(mediaType, requestbodyToString(bodyBuilder)); // See Edit 1
Request request = new Request.Builder()
.url(TARGET_URL)
.post(body)
.addHeader("content-type", mediaTypeString)
.addHeader("cache-control", "no-cache")
.build();
try {
System.out.println("Starting request.");
Response response = client.newCall(request).execute();
String targetUrl = request.url().toString() + bodyToString(request);
System.out.println("request: " + targetUrl);
String responseBodyString = response.body().string();
System.out.println("response: " + responseBodyString);
return responseBodyString;
} catch (IOException ex) {
System.out.println(ex);
}
Like I said, I keep getting a returned JSON of {"error":"invalid_client"}, and when I navigate to the URL I'm making the request to through a web browser it shows HTTP ERROR 405.
I'd love to provide as much additional information as you need. Thanks!
Edit 1: The second parameter of this used to be "bodyBuilder.toString()", but I changed it because I realized it wasn't actually sending the body. The result is still the same - {"error":"invalid_client"}. The method now used comes from here.
I figured out what it was - I hadn't actually been writing the authentication_code to the file, only adding it to another JSONObject. Oops. :)

HTTP post/API request works when sent from CURL on bash, fails from Apache http

I'm trying to use apache http components to interface with the Spotify api. The request I'm trying to send is detailed here under #1. When I send this request from bash using curl
curl -H "Authorization: Basic SOMETOKEN" -d grant_type=client_credentials https://accounts.spotify.com/api/token
I get back a token like the website describes
However the following java code, which as far as I can tell executes the same request, gives back a 400 error
Code
String encoded = "SOMETOKEN";
CloseableHttpResponse response = null;
try {
CloseableHttpClient client = HttpClients.createDefault();
URI auth = new URIBuilder()
.setScheme("https")
.setHost("accounts.spotify.com")
.setPath("/api/token")
.setParameter("grant_type", "client_credentials")
.build();
HttpPost post = new HttpPost(auth);
Header header = new BasicHeader("Authorization", "Basic " + encoded);
post.setHeader(header);
try {
response = client.execute(post);
response.getEntity().writeTo(System.out);
}
finally {
response.close();
}
} catch (Exception e) {
e.printStackTrace();
}
Error
{"error":"server_error","error_description":"Unexpected status: 400"}
The URI that the code prints is looks like this
https://accounts.spotify.com/api/token?grant_type=client_credentials
And the header looks like this
Authorization: Basic SOMETOKEN
Am I not constructing the request correctly? Or am I missing something else?
Use form url-encoding for the data in the body with the content-type application/x-www-form-urlencoded :
CloseableHttpClient client = HttpClients.createDefault();
HttpPost post = new HttpPost("https://accounts.spotify.com/api/token");
post.setHeader(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
post.setHeader(HttpHeaders.AUTHORIZATION, "Basic " + encoded);
StringEntity data = new StringEntity("grant_type=client_credentials");
post.setEntity(data);
HttpResponse response = client.execute(post);

Twitter oauth2 using javax.ws.rs

I have this request for twitter using javax.ws.rs
WebTarget target = new WebTargetBuilder(client, OAUTH_API_ENDPOINT).build();
Builder request = target
.request(MediaType.APPLICATION_JSON)
.header("Authorization", "Basic " + encodedCredentials)
.header("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8");
Response postResponse = request
.post(Entity.entity("grant_type=client_credentials", MediaType.TEXT_PLAIN));
System.out.println(postResponse.readEntity(String.class));
encodedCredentials are my consumer secret and consumer key encoded in base 64.
The request I'm trying to do is:
POST /oauth2/token HTTP/1.1
Host: api.twitter.com
User-Agent: My Twitter App v1.0.23
Authorization: Basic eHZ6MWV2RlM0d0VFUFRHRUZQSEJvZzpMOHFxOVBaeVJn
NmllS0dFS2hab2xHQzB2SldMdzhpRUo4OERSZHlPZw==Content-Type: application/x-www- form-urlencoded;charset=UTF-8
Content-Length: 29
Accept-Encoding: gzip
grant_type=client_credentials
I keep getting 403 Forbidden: {"errors":[{"code":170,"message":"Missing required parameter: grant_type","label":"forbidden_missing_parameter"}]}
It seems that the post body isn't set correctly, anyone know how to set it?
What you could try is to change the content type of the POST request body/entity like this:
.post(Entity.entity("grant_type=client_credentials", MediaType.APPLICATION_FORM_URLENCODED)
I have used same in PHP and i think you missed required parameters like oauth_signature
So the final code to obtain the bearer token from Twitter having the consumer key and consumer secret looks like this:
private static final String OAUTH_API_ENDPOINT = "https://api.twitter.com/oauth2/token";
private String consumerKey = "your consumer key";
private String consumerSecret = "your consumer secret";
// Constructs the request for requesting a bearer token and returns that
// token as a string
public String requestBearerToken() throws IOException, InterruptedException, ExecutionException {
String encodedCredentials = encodeCredentials();
Client client = ClientBuilder.newClient();
WebTarget target = new WebTargetBuilder(client, OAUTH_API_ENDPOINT).build();
Response postResponse = target
.request(MediaType.APPLICATION_JSON)
.header("Authorization", "Basic " + encodedCredentials + "Content-Type: application/x-www-form-urlencoded;charset=UTF-8")
.post(Entity.entity("grant_type=client_credentials", MediaType.APPLICATION_FORM_URLENCODED));
return postResponse.toString();
}
// Encodes the consumer key and secret to create the basic authorization key
public String encodeCredentials() {
try {
String encodedConsumerKey = URLEncoder.encode(consumerKey, "UTF-8");
String encodedConsumerSecret = URLEncoder.encode(consumerSecret,
"UTF-8");
String fullKey = encodedConsumerKey + ":" + encodedConsumerSecret;
byte[] encodedBytes = Base64.encodeBase64(fullKey.getBytes());
return new String(encodedBytes);
} catch (UnsupportedEncodingException e) {
return new String();
}
}

Categories