3

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?

stu2
  • 67
  • 1
  • 8

3 Answers3

1

Have you given service account access to your Google Apps account? You can find out how to that here: https://developers.google.com/+/domains/authentication/delegation#delegate_domain-wide_authority_to_your_service_account

Following code works for me:

key = Google::APIClient::KeyUtils.load_from_pkcs12('tmp/##########-privatekey.p12', 'notasecret')
client = Google::APIClient.new({:application_name => "example-app", :application_version => "1.0"})
client.authorization = Signet::OAuth2::Client.new(
  :person => 'name@example.com',
  :token_credential_uri => 'https://accounts.google.com/o/oauth2/token',
  :audience => 'https://accounts.google.com/o/oauth2/token',
  :scope => 'https://www.googleapis.com/auth/drive.readonly',
  :issuer => '123456789@developer.gserviceaccount.com',
  :signing_key => key)
client.authorization.fetch_access_token!

drive = client.discovered_api('drive', 'v2')
result = client.execute(api_method: drive.files.list)
Milos
  • 311
  • 3
  • 9
1

There is a long thread regarding this on GitHub which seems to indicate the problem is related to the system's date and time being "a little off." The suggested solution is to run sudo ntpdate ntp.ubuntu.com.

The thread is closed but it does have a link to this information from Google about "Invalid Grant".

Chip Roberson
  • 532
  • 3
  • 12
0

Never was able to figure out how to get past the invalid_grant error.

My solution was to get a refresh token using the normal webapp api. Once retrieved it seems to be usable indefinitely so the end result appears to be the same.

stu2
  • 67
  • 1
  • 8