Insufficient Permission when run youtube retriving comments - java

This is my whole code. I want to give a video ID which from youtube to get the comments related to this vedio ID. But always show that I have Insufficient Permission.
I have tried to address this, and found youtube .commentThreads().list("snippet").setVideoId("tLTm_POao1c") .setTextFormat("plainText").execute(); is the problem. Specifically, execute() in this line calls "Insufficient Permission".
Why is this?
package com.google.api.services.samples.youtube.cmdline.youtube_cmdline_addsubscription_sample;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;
import com.google.api.client.util.Preconditions;//aiyamaya
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.java6.auth.oauth2.FileCredentialStore;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
//import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.ResourceId;
import com.google.api.services.youtube.model.Subscription;
import com.google.api.services.youtube.model.SubscriptionSnippet;
import com.google.common.collect.Lists;
import com.google.api.services.youtube.model.CommentThreadListResponse;
import com.google.api.services.youtube.model.CommentThread;
import com.google.api.services.youtube.model.CommentSnippet;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.samples.youtube.cmdline.youtube_cmdline_addsubscription_sample.Auth;
//import com.google.api.services.samples.youtube.cmdline.Auth;
/**
* Demo of subscribing user to a channel using the YouTube Data API (V3) with
* OAuth2 for authorization.
*
* #author Ibrahim Ulukaya
*/
public class AddSubscription {
/** Global instance of the HTTP transport. */
// private static final HttpTransport HTTP_TRANSPORT = new
// NetHttpTransport();
/** Global instance of the JSON factory. */
// private static final JsonFactory JSON_FACTORY = new JacksonFactory();
/** Global instance of Youtube object to make all API requests. */
private static YouTube youtube;
public static void main(String[] args) {
System.setProperty("proxySet", "true");
System.setProperty("proxyHost", "bproxy.rmit.edu.au");
System.setProperty("proxyPort", "8080");
List<String> scopes = Lists
.newArrayList("https://www.googleapis.com/auth/youtube");
try {
// Authorization.
Credential credential = Auth.authorize(scopes, "commentthreads");
// This object is used to make YouTube Data API requests.
youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT,
Auth.JSON_FACTORY, credential).setApplicationName(
"youtube-cmdline-commentthreads-sample").build();
// YouTube object used to make all API requests.
CommentThreadListResponse videoCommentsListResponse = youtube
.commentThreads().list("snippet").setVideoId("tLTm_POao1c")
.setTextFormat("plainText").execute();
List<CommentThread> videoComments = videoCommentsListResponse
.getItems();
} catch (GoogleJsonResponseException e) {
System.err.println("GoogleJsonResponseException code: "
+ e.getDetails().getCode() + " : "
+ e.getDetails().getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("IOException: " + e.getMessage());
e.printStackTrace();
} catch (Throwable t) {
System.err.println("Throwable: " + t.getMessage());
t.printStackTrace();
}
}
/*
* Returns a channel id (String) from user via the terminal.
*/
}
This is the error information:
May 22, 2015 8:19:15 AM com.google.api.client.util.store.FileDataStoreFactory setPermissionsToOwnerOnly
WARNING: unable to change permissions for everybody: C:\Users\E18300\.oauth-credentials
May 22, 2015 8:19:15 AM com.google.api.client.util.store.FileDataStoreFactory setPermissionsToOwnerOnly
WARNING: unable to change permissions for owner: C:\Users\E18300\.oauth-credentials
2015-05-22 08:19:15.192:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
2015-05-22 08:19:15.193:INFO::jetty-6.1.26
2015-05-22 08:19:15.212:INFO::Started SocketConnector#localhost:8080
2015-05-22 08:19:20.433:INFO::Stopped SocketConnector#localhost:8080
GoogleJsonResponseException code: 403 : Insufficient Permission
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Insufficient Permission",
"reason" : "insufficientPermissions"
} ],
"message" : "Insufficient Permission"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:321)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1045)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at com.google.api.services.samples.youtube.cmdline.youtube_cmdline_addsubscription_sample.AddSubscription.main(AddSubscription.java:86)

The documentation lacks in this part, but you need to use the scope https://www.googleapis.com/auth/youtube.force-ssl to retrieve comments from the YouTube API. Took me way too much time to solve this issue.

var OAUTH2_SCOPES = [
'https://www.googleapis.com/auth/youtube',
'https://www.googleapis.com/auth/youtube.force-ssl'
];
to retrieve comments from the YouTube API add
https://www.googleapis.com/auth/youtube.force-ssl
this into OAUTH2_SCOPES array

As the error message indicates, your request does not have sufficient permissions. If you look at the API Reference Overview you will see:
Every request must either specify an API key (with the key parameter) or provide an OAuth 2.0 token. Your API key is available in the API console's API Access pane for your project.
For example I am able to view the comment thread list for a video by making a GET request to this link in the browser directly:
https://www.googleapis.com/youtube/v3/commentThreads?part=snippet&key=YOUR_KEY&videoId=tLTm_POao1c. You will need to replace YOUR_KEY with your application key that you can find in your Google developer console.
I don't know why the code sample for comment threads does not mention anything about the need to include the API key (probably because it is assumed that you read the API Overview first). But
if you look at this other code sample, you will see that you can include a developer key in a local file that you can load into a Properties object:
// Read the developer key from the properties file.
Properties properties = new Properties();
try {
InputStream in = Search.class.getResourceAsStream("/" + PROPERTIES_FILENAME);
properties.load(in);
} catch (IOException e) {
System.err.println("There was an error reading " + PROPERTIES_FILENAME + ": " + e.getCause()
+ " : " + e.getMessage());
System.exit(1);
}
Further down the line, the api key is extracted from the Properties object and is used in the search API call:
// Set your developer key from the Google Developers Console for
// non-authenticated requests. See:
// https://console.developers.google.com/
String apiKey = properties.getProperty("youtube.apikey");
search.setKey(apiKey);
search.setQ(queryTerm);
In a similar manner, you can call setKey() on your code, as described by the JavaDocs: https://developers.google.com/resources/api-libraries/documentation/youtube/v3/java/latest/com/google/api/services/youtube/YouTube.CommentThreads.List.html#setKey(java.lang.String)
So, you may need to add something like this:
CommentThreadListResponse videoCommentsListResponse = youtube.commentThreads()
.list("snippet")
.setKey(YOUR_KEY)
.setVideoId("tLTm_POao1c")
.setTextFormat("plainText")
.execute();
You don't even need the Properties file, unless you plan to change the API key after you write the code and deploy it.

You only need a key to retrieve comments. Something like this:
String apiUrl = "https://www.googleapis.com/youtube/v3/commentThreads?part=snippet%2Creplies&videoId=" + ytId + "&moderationStatus=published&order=relevance&maxResults=5&key=" + apiKey;
Then handle the Json response.

Related

Reading labels works but reading messages results in ACCESS_TOKEN_SCOPE_INSUFFICIENT

I have created one poc using Gmail API which read all email and print on console. I have take refrence from Gmail api Java quickstart.
I have follows all the steps like create project, Gmail API enable, OAuth credentials in google cloud console
The problem is, when I run the code all the labels are printed successfully but I'm not able to read mail messages. Some an error are getting which are below:
> Task :GmailQuickstart.main()
Labels:
- CHAT
- SENT
- INBOX
- IMPORTANT
- TRASH
- DRAFT
- SPAM
- CATEGORY_FORUMS
- CATEGORY_UPDATES
- CATEGORY_PERSONAL
- CATEGORY_PROMOTIONS
- CATEGORY_SOCIAL
- STARRED
- UNREAD
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
GET https://gmail.googleapis.com/gmail/v1/users/me/messages
{
"code": 403,
"details": [
{
"#type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "ACCESS_TOKEN_SCOPE_INSUFFICIENT"
}
],
"errors": [
{
"domain": "global",
"message": "Insufficient Permission",
"reason": "insufficientPermissions"
}
],
"message": "Request had insufficient authentication scopes.",
"status": "PERMISSION_DENIED"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:146)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:118)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:37)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:439)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1111)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:525)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:466)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:576)
at GmailQuickstart.main(GmailQuickstart.java:80)
> Task :GmailQuickstart.main() FAILED
Execution failed for task ':GmailQuickstart.main()'.
> Process 'command '/home/bhautik/Downloads/jdk-11.0.15.1_linux-x64_bin/data/usr/lib/jvm/jdk-11/bin/java'' finished with non-zero exit value 1
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
And my code was below:
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.GmailScopes;
import com.google.api.services.gmail.model.Label;
import com.google.api.services.gmail.model.ListLabelsResponse;
import com.google.api.services.gmail.model.ListMessagesResponse;
import com.google.api.services.gmail.model.Message;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/* class to demonstrate use of Gmail list labels API */
public class GmailQuickstart {
private static final String APPLICATION_NAME = "Gmail API Java Quickstart";
private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
private static final String TOKENS_DIRECTORY_PATH = "tokens";
private static final List<String> SCOPES = Collections.singletonList(GmailScopes.GMAIL_LABELS);
private static final String CREDENTIALS_FILE_PATH = "/credentials.json";
private static final String USER_ID = "me";
private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT)
throws IOException {
// Load client secrets.
InputStream in = GmailQuickstart.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
if (in == null) {
throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
}
GoogleClientSecrets clientSecrets =
GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
.setAccessType("offline")
.build();
LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
//returns an authorized Credential object.
return credential;
}
public static void main(String... args) throws IOException, GeneralSecurityException {
// Build a new authorized API client service.
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
Gmail service = new Gmail.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
.setApplicationName(APPLICATION_NAME)
.build();
// Print the labels in the user's account.
String user = "me";
ListLabelsResponse listResponse = service.users().labels().list(user).execute();
List<Label> labels = listResponse.getLabels();
if (labels.isEmpty()) {
System.out.println("No labels found.");
} else {
System.out.println("Labels:");
for (Label label : labels) {
System.out.printf("- %s\n", label.getName());
}
}
// Print the message
ListMessagesResponse response = service.users().messages().list(USER_ID).execute();
// List<Message> messages = response.getMessages();
List<Message> messages = new ArrayList<Message>();
while (response.getMessages() != null) {
messages.addAll(response.getMessages());
if (response.getNextPageToken() != null) {
String pageToken = response.getNextPageToken();
response = service.users().messages().list(USER_ID).setPageToken(pageToken).execute();
} else {
break;
}
}
for (Message message : messages) {
System.out.println(message.getId());
System.out.println(message.getPayload());
Message test = service.users().messages().get("me", message.getId()).execute();
System.out.println(test.getSnippet());
}
}
}
ACCESS_TOKEN_SCOPE_INSUFFICIENT is a very common error message. It comes from copying the example without understanding what its doing. This is googles fault for not explaining things better.
The quick start uses the lables.list method. This method runs on users private data so you used Oauth2 to request permission of the user to access their data.
The method can run with any of the following permissions being requested
Best practice is to only request the permissions you need. So the code is asking for the GmailScopes.GMAIL_LABELS permission which will only give you access to see the lables
Now to read a users messages the messges.listmethod you need to request permission with one of the following scopes
as you can see the label scope is not there. Thats because you need a higher level of permissions to access this data..
Solution:
Change the scope in your code to request one of the scopes needed for messgaes.list.
Then you need to reauthorize your application. YOu can do this in a few was.
delete the file found in TOKENS_DIRECTORY_PATH
change .authorize("user"); the text passed here to something else.
When you run your app again it should prompt you for authorization again.
I would comment but I have too few rep.
I guess you didn't properly set up the permissions of your access token. The error message suggessts, that you need a specific set of permissions to access the ressource

How to upload videos on Youtube to a particular youtube account on Android programatically

Here is my use case:
I want users to be able to upload video content from their devices directly to my youtube or a dedicated youtube account without leaving my app. First of all, is this possible? Please I will appreciate code samples. Thanks
This shows how to upload a video using an HTTP request.
There are code snippets that are also available in java (and kotlin is pretty similar).
In order to see how to upload a video, go to https://developers.google.com/youtube/v3/code_samples/code_snippets, select Videos under Resource and insert under method.
If you then click on Show code and select JAVA at the top, you will get this example code:
/**
* Sample Java code for youtube.videos.insert
* See instructions for running these code samples locally:
* https://developers.google.com/explorer-help/guides/code_samples#java
*/
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.InputStreamContent;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.Video;
import com.google.api.services.youtube.model.VideoSnippet;
import com.google.api.services.youtube.model.VideoStatus;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.Collection;
public class ApiExample {
// You need to set this value for your code to compile.
// For example: ... DEVELOPER_KEY = "YOUR ACTUAL KEY";
private static final String DEVELOPER_KEY = "YOUR_API_KEY";
private static final String APPLICATION_NAME = "API code samples";
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
/**
* Build and return an authorized API client service.
*
* #return an authorized API client service
* #throws GeneralSecurityException, IOException
*/
public static YouTube getService() throws GeneralSecurityException, IOException {
final NetHttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
return new YouTube.Builder(httpTransport, JSON_FACTORY, null)
.setApplicationName(APPLICATION_NAME)
.build();
}
/**
* Call function to create API service object. Define and
* execute API request. Print API response.
*
* #throws GeneralSecurityException, IOException, GoogleJsonResponseException
*/
public static void main(String[] args)
throws GeneralSecurityException, IOException, GoogleJsonResponseException {
YouTube youtubeService = getService();
// Define the Video object, which will be uploaded as the request body.
Video video = new Video();
// Add the snippet object property to the Video object.
VideoSnippet snippet = new VideoSnippet();
snippet.setCategoryId("22");
snippet.setDescription("Description of uploaded video.");
snippet.setTitle("Test video upload.");
video.setSnippet(snippet);
// Add the status object property to the Video object.
VideoStatus status = new VideoStatus();
status.setPrivacyStatus("private");
video.setStatus(status);
// TODO: For this request to work, you must replace "YOUR_FILE"
// with a pointer to the actual file you are uploading.
// The maximum file size for this operation is 137438953472.
File mediaFile = new File("YOUR_FILE");
InputStreamContent mediaContent =
new InputStreamContent("application/octet-stream",
new BufferedInputStream(new FileInputStream(mediaFile)));
mediaContent.setLength(mediaFile.length());
// Define and execute the API request
YouTube.Videos.Insert request = youtubeService.videos()
.insert("snippet,status", video, mediaContent);
Video response = request.setKey(DEVELOPER_KEY).execute();
System.out.println(response);
}
}
You can also look at another example java code for uploading a video to YouTube on GitHub.
Note that you will need to make a few changes to this:
Under android, you don't have a main. You will need to (1) put that code whereever you need to and you might want ro (2) do it asynchronously.
When using kotlin, you will also (3) need to modify the syntax accordingly.

How to determine if a PUT request to S3 is creating or overwriting an item?

Using the AWS Java SDK, I am trying to determine if a PUT request results in the creation of a new object or update of an existing object, without making a second REST API call.
My initial thought was to see if a different status code is returned. Unfortunately I don't see a way to access the HTTP response status code from PutObjectResult.
While looking at the SDK docs I found ObjectMetadata.getLastModified(). Unfortunately it returns null every time I use it.
This is the code I am using to troubleshoot this:
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.PutObjectResult;
public class Main {
public static void main(String[] args) {
AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
.withRegion(Regions.US_EAST_1)
.build();
try {
PutObjectResult result = s3Client.putObject("pail", "foo", "first");
System.out.println(result.getMetadata().getLastModified());
} catch (AmazonServiceException e) {
System.out.println(e.getStatusCode() + " " + e.getErrorMessage());
}
}
}
After the first PUT request:
After the second PUT request:
For context, I created a bucket specifically for this with default settings and no items.
Any idea why getLastModified returns null or even how to access HTTP response status codes from PutObjectResult?

Get post form twitter public profile in java

I am trying to review twitter public profile using twitter4J.
I tried the examples on twitter4j git location but it did not worked.
import java.util.ArrayList;
import java.util.List;
import twitter4j.Paging;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;
import twitter4j.conf.ConfigurationBuilder;
public class TwitterTimeLine {
public static void main(String[] args) {
ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setOAuthConsumerKey("");
cb.setOAuthConsumerSecret("");
cb.setOAuthAccessToken("");
cb.setOAuthAccessTokenSecret("");
Twitter twitter = new TwitterFactory(cb.build()).getInstance();
int pageno = 1;
String user = "google";
List<Status> statuses = new ArrayList<Status>();
while (true) {
try {
int size = statuses.size();
Paging page = new Paging(pageno++, 100);
statuses.addAll(twitter.getUserTimeline(user, page));
if (statuses.size() == size)
break;
}
catch(TwitterException e) {
e.printStackTrace();
}
}
System.out.println("Total: "+statuses.size());
}
}
But it always gives me error
400:The request was invalid. An accompanying error message will explain why. This is the status code will be returned during version 1.0 rate limiting(https://dev.twitter.com/pages/rate-limiting). In API v1.1, a request without authentication is considered invalid and you will get this response.
message - Bad Authentication data.
code - 215
Relevant discussions can be found on the Internet at:
http://www.google.co.jp/search?q=4be80492 or
http://www.google.co.jp/search?q=0a6306df
TwitterException{exceptionCode=[4be80492-0a6306df], statusCode=400, message=Bad Authentication data., code=215, retryAfter=-1, rateLimitStatus=null, version=4.0.4}
at twitter4j.HttpClientImpl.handleRequest(HttpClientImpl.java:164)
at twitter4j.HttpClientBase.request(HttpClientBase.java:57)
at twitter4j.HttpClientBase.get(HttpClientBase.java:75)
at twitter4j.TwitterImpl.get(TwitterImpl.java:1786)
at twitter4j.TwitterImpl.getUserTimeline(TwitterImpl.java:131)
at com.twitter.ibeat.iBeatTwitter.TwitterTimeLine.main(TwitterTimeLine.java:33)
400:The request was invalid. An accompanying error message will explain why. This is the status code will be returned during version 1.0 rate limiting(https://dev.twitter.com/pages/rate-limiting). In API v1.1, a request without authentication is considered invalid and you will get this response.
message - Bad Authentication data.
code - 215
Could you please help me to get this working.
Regards
Virendra Agarwal
Problem was solved using oAuth token and Query API from twitter4J.

BigQuery and OAuth2

I'm trying to access Google BigQuery using Service Account approach. My code is as follows:
private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
GoogleCredential credentials = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("XXXXX#developer.gserviceaccount.com")
.setServiceAccountScopes(BigqueryScopes.BIGQUERY)
.setServiceAccountPrivateKeyFromP12File(
new File("PATH-TO-privatekey.p12"))
.build();
Bigquery bigquery = Bigquery.builder(HTTP_TRANSPORT, JSON_FACTORY).setHttpRequestInitializer(credentials)
.build();
com.google.api.services.bigquery.Bigquery.Datasets.List datasetRequest = bigquery.datasets().list(
"PROJECT_ID");
DatasetList datasetList = datasetRequest.execute();
if (datasetList.getDatasets() != null) {
java.util.List<Datasets> datasets = datasetList.getDatasets();
System.out.println("Available datasets\n----------------");
for (Datasets dataset : datasets) {
System.out.format("%s\n", dataset.getDatasetReference().getDatasetId());
}
}
But it throws the following exception:
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
"code" : 401,
"errors" : [ {
"domain" : "global",
"location" : "Authorization",
"locationType" : "header",
"message" : "Authorization required",
"reason" : "required"
} ],
"message" : "Authorization required"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:159)
at com.google.api.client.googleapis.json.GoogleJsonResponseException.execute(GoogleJsonResponseException.java:187)
at com.google.api.client.googleapis.services.GoogleClient.executeUnparsed(GoogleClient.java:115)
at com.google.api.client.http.json.JsonHttpRequest.executeUnparsed(JsonHttpRequest.java:112)
at com.google.api.services.bigquery.Bigquery$Datasets$List.execute(Bigquery.java:979)
The exception is fired on this line:
DatasetList datasetList = datasetRequest.execute();
I'm getting the account ID from Google's API console from the second line on the section that looks like this:
Client ID: XXXXX.apps.googleusercontent.com
Email address: XXXXX#developer.gserviceaccount.com
What am I missing?
Eureka! Both Eric's and Michael's code works well.
The error posted in the question can be reproduced by setting the time on the client machine incorrectly. Fortunately, it can be solved by setting the time on the client machine correctly.
Note: For what it's worth, I synchronized the time on a Windows 7 box using the "Update now" button in the "Internet Time Settings" dialog. I figured that should be pretty idiot-proof... but I guess I beat the system. It corrected the seconds but left the machine off by exactly one minute. The BigQuery call failed after that. It succeeded after I manually changed the time.
Our error handling code in the Java library needs to be improved a bit!
It looks like the signed JWT for requesting an OAuth access token is failing. You can see this by enabling the logs that #MichaelManoochehri mentioned above.
There's only a few things that I think could be causing this failure:
Invalid signature (using the wrong key)
Invalid e-mail address for the service account (I think that's been ruled out)
Invalid date/time stamp used for generating the signed blob (an issue date, and an expiration date)
Invalid scope (I think that's been ruled out)
You should check that your date/time is properly set on your server with the proper timezone -- sync'd to NTP. You can use time.gov to see the official US atomic clock time.
EDIT: The answer I gave below is relevant to using Google App Engine Service Accounts - leaving here for reference.
Double check that you have added your service account address to your project's team page as an owner.
I'd recommend using the AppIdentityCredential class to handle service account auth. Here's a small snippet that demonstrates this, and I'll add additional documentation about this on the BigQuery API developer page.
Also, make sure that you are using the latest version of the Google Java API client (as of today, it's version "v2-rev5-1.5.0-beta" here).
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.api.client.googleapis.extensions.appengine.auth.oauth2.AppIdentityCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.http.json.JsonHttpRequest;
import com.google.api.client.http.json.JsonHttpRequestInitializer;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.bigquery.Bigquery;
import com.google.api.services.bigquery.BigqueryRequest;
#SuppressWarnings("serial")
public class Bigquery_service_accounts_demoServlet<TRANSPORT> extends HttpServlet {
// ENTER YOUR PROJECT ID HERE
private static final String PROJECT_ID = "";
private static final HttpTransport TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
private static final String BIGQUERY_SCOPE = "https://www.googleapis.com/auth/bigquery";
AppIdentityCredential credential = new AppIdentityCredential(BIGQUERY_SCOPE);
Bigquery bigquery = Bigquery.builder(TRANSPORT,JSON_FACTORY)
.setHttpRequestInitializer(credential)
.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
public void initialize(JsonHttpRequest request) {
BigqueryRequest bigqueryRequest = (BigqueryRequest) request;
bigqueryRequest.setPrettyPrint(true);
}
}).build();
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/plain");
resp.getWriter().println(bigquery.datasets()
.list(PROJECT_ID)
.execute().toString());
}
}
Here is a complete snippet for reference:
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.bigquery.Bigquery;
import com.google.api.services.bigquery.Bigquery.Datasets;
import com.google.api.services.bigquery.model.DatasetList;
import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
public class BigQueryJavaServiceAccount {
private static final String SCOPE = "https://www.googleapis.com/auth/bigquery";
private static final HttpTransport TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
public static void main(String[] args) throws IOException, GeneralSecurityException {
GoogleCredential credential = new GoogleCredential.Builder().setTransport(TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("XXXXXXX#developer.gserviceaccount.com")
.setServiceAccountScopes(SCOPE)
.setServiceAccountPrivateKeyFromP12File(new File("my_file.p12"))
.build();
Bigquery bigquery = Bigquery.builder(TRANSPORT, JSON_FACTORY)
.setApplicationName("Google-BigQuery-App/1.0")
.setHttpRequestInitializer(credential).build();
Datasets.List datasetRequest = bigquery.datasets().list("publicdata");
DatasetList datasetList = datasetRequest.execute();
System.out.format("%s\n", datasetList.toPrettyString());
}

Categories