EzDevInfo.com

google-api-ruby-client

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.


Source: (StackOverflow)

List of calendar methods Google API ruby client

This is my code:

@token = @auth["credentials"]["token"]
client = Google::APIClient.new
client.authorization.access_token = @token
service = client.discovered_api('calendar', 'v3')
@result = client.execute(
  :api_method => service.calendar_list.list,
  :parameters => {},
  :headers => {'Content-Type' => 'application/json'})

My question is: Where can I find a list of :api_method for Google calendar API?


Source: (StackOverflow)

Advertisements

Mocking methods in google ruby api client

I am trying to mock some methods that use the google-api-ruby-client to make some testing without actually calling the api. Authentication and client and activities methods are taken from the example found on the github page (see link above), which is why I skipped it here.

The method from the example is the following:

def activities
  result = client.execute(
    :api_method => plus.activities.list,
    :parameters => {'collection' => 'public', 'userId' => 'me'}
  )
  return result.data
end

I previously tried to stub the client (even chained with the execute) methods, however this results in authorization requests for oauth, which the gem uses underneath followed by mocks for the plus.activities.list methods. Is there a way to directly mock client.exectute to return something useful while skipping the whole chain?


Source: (StackOverflow)

Resumable YouTube Data API v3 uploads using Ruby

I am currently using the google-api-ruby-client to upload videos to Youtube API V3, but I can't find a way of getting the Youtube ID that is created by a resumable upload. The code I am trying to use is along the lines of:

media = Google::APIClient::UploadIO.new(file_path, 'application/octet-stream')
yt_response = @client.execute!({
  :api_method => @youtube.videos.insert,
  :parameters => {
    :part => 'snippet,status',
    'uploadType' => 'resumable'
  },
  :body_object => file_details,
  :media => media
})
return JSON.parse(yt_response.response.body)

But unfortunately for resumable uploads, yt_response.response.body is blank. If I change the 'uploadType' to 'multipart' then body is a JSON blob that contains the Youtube ID. The response for a resumable upload though is only the resumable session URI for the upload with an empty body. How do I go from that URI into the Youtube ID I just created?


Source: (StackOverflow)

How do I add an IPv6 address to Google API Credentials?

I have a Ruby app in development that uses the Google API (custom search engine). It's been working great with the Public API access key.

I just upgraded my internet to Uverse and suddently the Google API stopped working. I figured out the issue was the IP address. My Uverse modem uses IPv6.

Unfortunately, Google Developer Public API access keys seem to only accept IPv4 addresses so when I try to add my IPv6 address I get the error message: "The IP address is invalid".

Has anyone been able to get this to work? I would prefer not to implement oAuth if I can avoid it.


Source: (StackOverflow)

Determining the parameters for "discovered_api"

This might be a really stupid question, but how do you determine the parameters to pass in the client "discovered_api" call? and then what is the executed "api_method"

For instance, I'm trying to call the Admin SDK Users List call which is "GET https://www.googleapis.com/admin/directory/v1/users".

There doesn't seem to be a clear way of extracting this from the API reference, or am I just looking in the wrong place?


Source: (StackOverflow)

Google plus insert activity on stream

Tough time inserting an activity to google plus stream. After referring google developers guide. I found an example for java - https://developers.google.com/+/domains/posts/creating

Is there a similar example to execute the activites.insert query using google-api-ruby-client.

I followed following steps:

Define access to app via omniauth-google-oauth2

GOOGLE_CONSUMER_KEY      = google_config['KEY']
GOOGLE_CONSUMER_SECRET   = google_config['SECRET']
google_scope = "userinfo.email,
                userinfo.profile,
                plus.login,
                plus.me,
                plus.media.upload,
                plus.profiles.read,
                plus.stream.read,
                plus.stream.write,
                plus.circles.read,
                plus.circles.write"

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :google_oauth2, GOOGLE_CONSUMER_KEY, GOOGLE_CONSUMER_SECRET,
    {
        name: 'google',
      scope: google_scope,
      prompt: 'consent'
    }
end

Use the token and refresh token to execute api calls google-api-ruby-client. Am able to list the activities using "plus", but to insert an activity I should use plusDomains.

client = Google::APIClient.new(:application_name =>'Demo GooglePlus',:application_version => '1.0.0')

plus = client.discovered_api('plus')

plusd = client.discovered_api('plusDomain')

client_secrets = Google::APIClient::ClientSecrets.load 

auth=client_secrets.to_authorization

auth.update_token!(access_token: 'aRandomToken', refresh_token: 'aRandomRefreshToken')

result = client.execute(:api_method => plus.activities.list,:parameters => {'collection' => 'public', 'userId' => 'me'}, :authorization => auth)
>> This works, returns the list of activities

Using plus Domain

result = client.execute(:api_method => plusd.activities.insert,:parameters => {'collection' => 'public', 'userId' => 'me'}, :authorization => auth)
>> Returns 403 Forbidden

Later I realized that google api requires domain wide delegaton to use the domains api(I think thats correct?) https://developers.google.com/+/domains

https://developers.google.com/+/domains/getting-started#accessing_the_apis - Will the oauth used in Step 1 above would suffice ?

https://developers.google.com/+/domains/quickstart/python - Is there anything available in RUBY

I tried the service account setup also, created a business app and followed a service_account example

But still not luck.

Trying on terminal

curl -v -H "Content-Type: application/json" -H "Authorization: OAuth ya12.AqwqwwAS1212grcECQ3iVAlg" -d "{'object':{'content':'Test message'},'access':{'items':[{'type' : 'domain'}],'domainRestricted':true}}" -X POST https://www.googleapis.com/plus/v1domains/people/me/activities

Results in ->
{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "forbidden",
    "message": "Forbidden"
   }
  ],
  "code": 403,
  "message": "Forbidden"
 }
}

May I get some help in inserting an activity on google plus user steam ?

Thanks!


Source: (StackOverflow)

Has anyone figured how how the create a user with the Admin Directory api using the google-api-ruby-client?

I've been trying a few combinations but can't seem to come up with something that works. More information about the API I'm asking about can be found here https://developers.google.com/admin-sdk/directory/v1/reference/users/insert . I have a feeling I'm just not setting up the request correctly. The following bit of code is known to work. I use it to set up the client that is able to query all the users.

client = Google::APIClient.new(:application_name => "myapp", :version => "v0.0.0")
client.authorization = Signet::OAuth2::Client.new(
     :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
     :audience => 'https://accounts.google.com/o/oauth2/token',
     :scope => "https://www.googleapis.com/auth/admin.directory.user",
     :issuer => issuer,
     :signing_key => key,
     :person => user + "@" + domain)
client.authorization.fetch_access_token!
api = client.discovered_api("admin", "directory_v1")

When I try to use the following code

parameters = Hash.new
parameters["password"] = "ThisIsAPassword"
parameters["primaryEmail"] = "tstacct2@" + domain
parameters["name"] = {"givenName" => "Test", "familyName" => "Account2"}
parameters[:api_method] = api.users.insert
response = client.execute(parameters)

I always get back the same error "code": 400, "message": "Invalid Given/Family Name: FamilyName"

I've observed a few things while looking into this particular API. If I print out the parameters for both the list and the insert functions e.g

puts "--- Users List ---"
puts api.users.list.parameters
puts "--- Users Insert ---"
puts api.users.insert.parameters

Only the List actually displays the parameters

--- Users List ---
  customer
  domain
  maxResults
  orderBy
  pageToken
  query
  showDeleted
  sortOrder
--- Users Insert ---

This leaves me wondering if the ruby client is unable to retrieve the api and therefore unable to submit the request correctly or if I'm just doing something completely wrong.

I'd appreciate any idea's or direction that might help set me on the right path.

Thank you,

James


Source: (StackOverflow)

Ruby real time google analytics API

I am trying to get activeVisitors with the google-api-ruby-client. The client is listed in the real time google analytics API docs here however I see nothing in the docs about using it for real time api.

I see the function discovered_api however I see no list for posisble parameters for the API name.

Example for Regular Analytics API:

# Get the analytics API
analytics = client.discovered_api('analytics','v3')

Does anyone know how to use this client to get real time active visitors?

Here is the code I am trying to use:

require 'google/api_client'
require 'date'

# Update these to match your own apps credentials
service_account_email = 'xxxxxxxxxxxxx@developer.gserviceaccount.com' # Email of service account
key_file = '/path/to/key/privatekey.p12' # File containing your private key
key_secret = 'notasecret' # Password to unlock private key
profileID = '111111111' # Analytics profile ID.

# Get the Google API client
client = Google::APIClient.new(:application_name => '[YOUR APPLICATION NAME]',
:application_version => '0.01')

# Load your credentials for the service account
key = Google::APIClient::KeyUtils.load_from_pkcs12(key_file, key_secret)
client.authorization = Signet::OAuth2::Client.new(
:token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
:audience => 'https://accounts.google.com/o/oauth2/token',
:scope => 'https://www.googleapis.com/auth/analytics.readonly',
:issuer => service_account_email,
:signing_key => key)

# Start the scheduler
SCHEDULER.every '1m', :first_in => 0 do

# Request a token for our service account
client.authorization.fetch_access_token!

# Get the analytics API
analytics = client.discovered_api('analytics','v3')

# Execute the query
visitCount = client.execute(:api_method => analytics.data.ga.get, :parameters => {
'ids' => "ga:" + profileID,
'metrics' => "ga:activeVisitors",
})

# Update the dashboard
send_event('current_visitors', { current: visitCount.data.rows[0][0] })
end

Error returned:

Missing required parameters: end-date, start-date.

Source: (StackOverflow)

Receiving error 403 in Google Drive API - Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup

I'm using the Google Drive API for ruby, and I'm trying to insert a file into an user drive. I can insert the file with success, but then, when I try to get the file Self Link, this is the URL returned https://www.googleapis.com/drive/v2/files/1PxrbKaO2xwOonUO0TB0FO3pkZDnSmRKTvIUmXw0vL6w, that says that i have exceeded the number of unauthenticated requests.

Well, I'm pretty sure I'm authenticated, because I followed all the tutorials and the code is almost the same.

Anyone knows why is this happening? why can I insert the file, but can't view it's Self Link?

Here is the code of the creation of a document in the drive, after the user allows the app with offline access:

SCOPES = [
              'https://www.googleapis.com/auth/drive',
              'https://www.googleapis.com/auth/userinfo.email',
              'https://www.googleapis.com/auth/userinfo.profile'
          ]

class DriveAuthenticator

    def self.create_document(user, title, description, parent_title, user_array)
        client = DriveAuthenticator.initiate_client
        if user.google_id.present?
            if DriveAuthenticator.authenticate_client client, user
                parent_id = get_parent_id client, parent_title
                file_data = insert_empty_file client, title, description, DOCUMENT_MIME_TYPE, parent_id
                return file_data.selfLink
            end
        end
    end

    private
    def self.initiate_client
        client = Google::APIClient.new(:application_name => 'stuff_app')

        credentials = Google::APIClient::ClientSecrets.load

        client.authorization.client_id = credentials.client_id
        client.authorization.client_secret = credentials.client_secret
        client.authorization.redirect_uri = credentials.redirect_uris.first
        client.authorization.scope = SCOPES
        client
    end

    private
    def self.get_token_by_refresh_token(client, refresh_token)
        client.authorization.refresh_token = refresh_token
        client.authorization.grant_type = 'refresh_token'
        client.authorization.fetch_access_token!
    end

    private
    def self.insert_empty_file(client, title, description, mime_type, parent_id)
        drive = client.discovered_api('drive', 'v2')
        file = create_file_schema drive, title, description, mime_type, parent_id
        result = client.execute(
          :api_method => drive.files.insert,
          :body_object => file)
        if result.status == 200
            result.data
        else
            puts "An error occurred: #{result.data['error']['message']}"
            nil
        end
    end

    private
    def self.create_file_schema(drive, title, description, mime_type, parent_id)
        file = drive.files.insert.request_schema.new({
            'title' => title,
            'description' => description,
            'mimeType' => mime_type
        })
        file.parents = [{'id' => parent_id}]
        file
    end

end

Source: (StackOverflow)

Google Calendar integration in a Rails App

My rails app will allow to create appointments. These appointments should then be exported to each users' google calendar.

I have installed omniauth-google-oauth2, and got my api key, client_id and client_secret for a Web application from Google's API Console.

I can authenticate users with omniauth, and store the access_token, refresh_token and expires_at date into my database, for later use.

When the time comes to export events to each users' google calendar (done in a background job) I get a response of Invalid Credentials.

What am I doing wrong?

Note: I can access user calender immediately after he authorizes in oauth, but not after some time passes.

Code:

sessions_controller

/auth/:provider/callback routes to this method:

auth = request.env["omniauth.auth"]
# Save token of user
current_user.google_auth_token         = auth["credentials"]["token"]
current_user.google_auth_refresh_token = auth["credentials"]["refresh_token"]
current_user.google_auth_expires_at    = Time.at auth["credentials"]["expires_at"]
current_user.save

omniauth config

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"], ENV["GOOGLE_CLIENT_SECRET"], {
    access_type: 'offline',
    scope: 'userinfo.email,calendar'
  }
end

getting access to create users calendars

client = Google::APIClient.new
client.authorization.refresh_token = app.carer.google_auth_refresh_token
client.authorization.access_token = app.carer.google_auth_token
if client.authorization.refresh_token && client.authorization.expired?
  client.authorization.fetch_access_token!
end
service = client.discovered_api('calendar', 'v3')
result = client.execute(:api_method => service.calendar_list.list)
# results in auth error, Invalid Credentials ...

Source: (StackOverflow)

Google Service Account authorize() returns invalid_grant error

I've carefully reviewed Steve Bazyl's presentation at https://www.youtube.com/watch?v=iK14bfd6qhs and relevant API docs on google. I'm using the Service Account email id for my gmail account, and am using the private key downloaded from the Console.

But when I run the test client modeled after the one Steve showed in his presentation I consistently get

 Signet::AuthorizationError:
   Authorization failed.  Server message:
   {
     "error" : "invalid_grant"
   }

I get the same error message if I add garbage letters to the email or scope passed to JWTAsserter. Clearly something wrong but I can't seem to figure out how to troubleshoot this.

Here's the client code I'm running (in a rails rspec file):

client = Google::APIClient.new

key_file = '/Users/stu/projects/br/rails-app/######-privatekey.p12'
key = Google::APIClient::KeyUtils.load_from_pkcs12(key_file, 'notasecret')
Rails.logger.info "Private key? #{key.private?}"

asserter = Google::APIClient::JWTAsserter.new( 
  '#####-#######knp@developer.gserviceaccount.com', 
  "https://www.googleapis.com/auth/calendar", 
  key)
client.authorization = asserter.authorize()

I'm pretty well stuck, would definitely appreciate any troubleshooting advice.

Thanks!

Update

Thanks for sharing code that works for you Jack.

I've gone to my site's dev console and created a service account client p12 key. I then went to the site's Admin Console and added my client id granting site-wide authorization to the calendar API

In the Admin Console after adding the authorization it looks like this: XXXXXXXXXXXhnq.apps.googleusercontent.com Calendar (Read-Write) https://www.googleapis.com/auth/calendar

I downloaded the p12 key and used it in the code structure you provided. I also tried with the approach from Steve Bazyl's presentation:

asserter = Google::APIClient::JWTAsserter.new( 
  "XXXXXXXXXXX-hnq@developer.gserviceaccount.com", 
  "https://www.googleapis.com/auth/calendar", 
  key)
client.authorization = asserter.authorize("stu@XXXXXXXXXX.com")

In both cases I get the same output as before:

 Signet::AuthorizationError:
   Authorization failed.  Server message:
   {
     "error" : "invalid_grant"
   }

I get that same output if I type in junk instead of "XXXXs://www.googleapis.com/auth/calendar". The key is valid, and while it's clear I'm doing something wrong, I can't find any clues in the API or google about how to tell what it is.

Any ideas how to troubleshoot?


Source: (StackOverflow)

NameError: uninitialized constant Faraday::FlatParamsEncoder

I am using google_drive gem that depends on google-api-client and the gem versions are:

google_drive (1.0.1)
google-api-client (0.7.1)
faraday (0.8.9)
faraday_middleware (0.9.0)

Now, on using GoogleDrive:

session = GoogleDrive.login_with_oauth('access_token')

I am getting the following exception:

NameError: uninitialized constant Faraday::FlatParamsEncoder
from /Users/Admin/.rvm/gems/ruby-1.9.3-p551@############/gems/google-api-client-0.7.1/lib/google/api_client.rb:118:in `block in initialize'

Checked the code for the version of the google-api-client that I am using, here:

https://github.com/google/google-api-ruby-client/blob/google-api-client-0.7.1/lib/google/api_client.rb

Couldn't find anything unusual. Any help will be appreciated. Thanks


Source: (StackOverflow)

Integrating Google Plus with Rails

I already have the login (OAuth) piece working with my app, what I am trying to do now is pull down the authenticated users' activity list (status feed, for example).

The user has the option to pull this list down after the fact of them being authenticated and here is my code, thus far:

# User Model
  def gplus
    auth = authorizations.find_by_provider("gplus")
    client = Google::APIClient.new(application_name: "AppName", application_version: '1.0', authorization: nil)

    plus = client.discovered_api('plus', 'v1')

    result = client.execute(
      key: API["gplus"][Rails.env]["secret"],
      api_method: plus.people.get,
      parameters: { 'collection' => 'public', 'userId' => 'me'  }
    )

    return result.data
  end

Here is the problem I keep running into (from rails console)

    #<Google::APIClient::Schema::Plus::V1::Person:0x3fe649ed04bc 
DATA:{"error"=>{"errors"=>[{"domain"=>"usageLimits", "reason"=>"keyInvalid", "message"=>"Bad Request"}], "code"=>400, "message"=>"Bad Request"}}>

I am using the https://github.com/google/google-api-ruby-client... any reason why this won't work?


Source: (StackOverflow)

How to set the Google API user to impersonate using a Service Account (Ruby Client)?

I have a service account and I am using the OAuth2 gem together with the Google API Ruby Client:

require 'oauth2'
require 'google/api_client'

My objective is to fetch an access token which allows access to a specific user’s account and no other. I think this is often achieved using the sub parameter when using HTTP, but how do I do this using the Ruby client libraries above?

I can get an access token successfully and use it to access the drive v2 file list API. I always see a single "How to get started with Drive" document in the response and no other.

I suspect my attempt to impersonate a user has not succeeded. Basically I’m passing in an email address as a sub option to the function below:

client = Google::APIClient.new(...)
access_token = OAuth2::AccessToken.new(oauth2_client, client.authorization.access_token, {‘sub’ => ‘user@domain.com’} )

Presumably that isn’t the way to do this.

How to I retrieve an access token which is scoped to permit access impersonating a single user and no other?


Following Steve's comment I have dropped the intridea Gem and am now using Signet. I get a little further but I am stuck getting an access_denied error when I specify a :person. Without that I can authenticate but obviously I get access as the issuer.

require 'google/api_client'
...
client = Google::APIClient.new(:application_name => application_name, :application_version => application_version)
...
opts = {
  :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
  :audience => 'https://accounts.google.com/o/oauth2/token',
  :scope => scope,
  :issuer => service_account_email_address,
  :signing_key => key,
  :person => 'my.email@address.com'
})
client.authorization = Signet::OAuth2::Client.new(opts)
access_token = client.authorization.fetch_access_token!
...

>> client.authorization.fetch_access_token!
Signet::AuthorizationError: Authorization failed.  Server message:
{
  "error" : "access_denied",
  "error_description" : "Requested client not authorized."
}

I have a console project which I do a 'test install flow' on but the client does not seem to be trusted. Where do I look?

Thanks.


Source: (StackOverflow)