2
votes

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)
4

4 Answers

7
votes

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.

3
votes
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

0
votes

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.

0
votes

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.