Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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( 
  '#####-#######[email protected]', 
  "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( 
  "[email protected]", 
  "https://www.googleapis.com/auth/calendar", 
  key)
client.authorization = asserter.authorize("[email protected]")

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?

like image 357
stu2 Avatar asked Jan 24 '26 01:01

stu2


1 Answers

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 => '[email protected]',
  :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 => '[email protected]',
  :signing_key => key)
client.authorization.fetch_access_token!

drive = client.discovered_api('drive', 'v2')
result = client.execute(api_method: drive.files.list)
like image 181
Milos Avatar answered Jan 27 '26 00:01

Milos



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!