Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

YouTube API v3 with OAuth2: update and delete fail with "Insufficient Permission" error

I am trying to update and delete videos using the YouTube API v3 with OAuth2 for authentication via the google-api-client (0.6.4) Ruby gem. However, when I attempt to execute either of these two actions, I see the following error message:

Google::APIClient::ClientError: Insufficient Permission

Here's the odd thing: Using the exact same authentication procedure as with update and delete, I can insert (upload) successfully, no problem! So, I do not believe this is a problem with my authentication setup, but somewhere else in my code.

My read-write scope is always the same across any of these actions:

https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload

And according to the API documentation, that space-delimited set of scopes should cover insert, update and delete actions.

My client_id, client_secret, refresh_token are always the same for all these actions too -- so, that can't be the problem either, can it? Note that my program automatically obtains a new access_token when it expires, so, again, I do not believe that is where the problem lies.

To compare, here is what my insert (upload) code looks like (this works):

# Auth stuff, then...
@client.execute!(
  :api_method => @youtube.videos.insert,
  :body_object => body,
  :media => Google::APIClient::UploadIO.new(file_path, 'video/*'),
  :parameters => {
    'uploadType' => 'multipart',
    :part => body.keys.join(','),
  }
)

And here is what my delete code looks like (this fails):

# Auth stuff, then...
@client.execute!(
  :api_method => @youtube.videos.delete,
  :parameters => {
    'id' => youtube_id,
  }
)

What am I missing? Unfortunately, the YouTube API documentation for delete does not provide any examples, so I've got nothing to compare against. Please let me know if there is further information that I can provide to make my question clearer.

like image 395
GladstoneKeep Avatar asked Oct 01 '13 22:10

GladstoneKeep


1 Answers

I'm fairly sure all 11 views of this question (as of this writing) are me, but I'm going to post an answer just in case it helps someone in the future:

There was no problem with my code itself. The problem was when I initially created my refresh_token for this account.

For the uninitiated, the YouTube Data API (v3) does not support "service accounts," which, elsewhere in the Google API ecosystem, are the way you would normally accomplish setting up an OAuth2 auth'd client when the only client is yourself. The workaround is something you have to do by hand. Take the steps below:


First, go to the Google "API Console." There, under "API Access," you need to "Create a client ID" for an "installed application." This will give you a Client ID, a Client secret and a Redirect URI (you'll want the non-localhost one). Write these down.

Next, you need to manually obtain an authorization code by visiting a URL like the following in your favorite web browser, while logged in to the same account you just created the client ID for:

https://accounts.google.com/o/oauth2/auth
  ?client_id={client_id}
  &redirect_uri={redirect_uri}
  &scope={space separated scopes}
  &response_type=code
  &access_type=offline

Of course, you need to enter the client_id, redirect_uri and scope query parameters. In my case, this is where I went wrong. When I did this manual step, I should have put the scope param as:

https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtube.upload

But instead I just did https://www.googleapis.com/auth/youtube.upload, which is insufficient to update/delete videos!

Last, you need to obtain a refresh_token, by taking a URL like this:

https://accounts.google.com/o/oauth2/token
  ?code={authorization_code}
  &client_id={client_id}
  &client_secret={client_secret}
  &redirect_uri={redirect_uri}
  &grant_type=authorization_code

And curl'ing it with a command like:

$ curl https://accounts.google.com/o/oauth2/token -d "code=..."

This will return a JSON response that contains your refresh_token, which you then use when authorizing your request programmatically through the Google API.

like image 83
GladstoneKeep Avatar answered Sep 19 '22 16:09

GladstoneKeep