google-auth-library-ruby: can't get default credentials with service account

I did

$ cloud auth activate-service-account --key-file my_key.pem  xyz@developer.gserviceaccount.com

Then

$ gcloud auth list
Loading legacy configuration file: [~/.config/gcloud/properties]
This configuration file is deprecated and will not be read in a future
gcloud release.  gcloud will automatically migrate your current settings to the
new configuration format the next time you set a property by running:
  $ gcloud config set PROPERTY VALUE
You may also run:
  $ gcloud init
to create a new configuration and walk you through initializing some basic
settings.  You can find more information on named configurations by running:
  $ gcloud topic configurations

Credentialed accounts:
 - xyz@developer.gserviceaccount.com (active)
...

Then I did

$ gcloud init
...

All went fine but then I still can’t login:

[3] pry(#<DefaultWorld>)> Google::Auth.get_application_default(@config[:scopes])
RuntimeError: Could not load the default credentials. Browse to
https://developers.google.com/accounts/docs/application-default-credentials
for more information
from ~/.gem/ruby/gems/googleauth-0.5.1/lib/googleauth.rb:119:in `get_application_default'

Two things are strange. That after login, the sdk tool still not very happy with format used. And after init the ruby library can’t find credentials.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 1
  • Comments: 22 (3 by maintainers)

Most upvoted comments

To use application default credentials with service account, you will need to download the service account json file from google developers console and have the GOOGLE_APPLICATION_CREDENTIALS environment variable point to this file.

On a similar not, to use application default credentials with user credentials, you will need to run “gcloud auth login”.

EDIT: Starting in gcloud SDK v128.0.0, gcloud auth login no longer writes Application Default Credentials. Use gcloud auth application-default login instead.

Go to google auth page and download .json file which will contain your credentials and secret keys. Go to you terminal and type: export GOOGLE_APPLICATION_CREDENTIALS=/path/to/credential.json

@kevlarr, yeah, it’s odd that it is not documented. Eventually I ended up doing (after inspecting the source code):

        File.open(expand_private_path(config[:json_cred]), "r") do |json_io|
          @compute.authorization = Google::Auth::DefaultCredentials.make_creds(
              scope: config[:scopes],
              json_key_io: json_io
          )
        end

where config[:json_cred] is a file with content [1]:

{
  "private_key_id": "anotherstring",
  "private_key": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n",
  "client_email": "string-anotherstring@developer.gserviceaccount.com",
  "client_id": "string-anotherstring.apps.googleusercontent.com",
  "type": "service_account"
}

and scopes is ["https://www.googleapis.com/auth/compute"].

I think API can be more convenient and better documented [2].

[1] another example in spec/googleauth/credentials_spec.rb - https://github.com/google/google-auth-library-ruby/blob/master/spec/googleauth/credentials_spec.rb#L38-L44 [2] API was documented in #110

update (2008-07-24): added link to docs, private_key_id and client_id JSON elements

Yeah, readme is very misleading and wrong.

@akostadinov Oh, interesting… I wound up just using the expected ENV names, since it doesn’t conflict with anything we currently have, but hopefully it stays that way…?

scopes = ["https://www.googleapis.com/auth/calendar"]
auth = ::Google::Auth.new_application_credentials(scopes)
service = ::Google::Apis::CalendarV3::CalendarService.new
service.authorization = auth
service.authorization.fetch_access_token!

And the only env vars I have configured are: “GOOGLE_CLIENT_ID”, “GOOGLE_CLIENT_EMAIL”, “GOOGLE_ACCOUNT_TYPE”, “GOOGLE_PRIVATE_KEY”

I’m not having any development issues with not using a file and configuring the path to it, but I’m having strange issues (the same “PUB/PRIVATE” error message you received) if I run tests in a very specific order.

@akostadinov, @kevlarr: This is the solution that I’ve come up with for my rails app, based upon my reading of the documentation. What are your thoughts? The getGAToken method below returns the access token hash. Hope this helps somebody else who struggled with this besides me.

require 'google/apis/analytics_v3'
require 'googleauth'

class DashboardController < ApplicationController

...
  protected
  def getGAToken
    scope = 'https://www.googleapis.com/auth/analytics.readonly'
    analytics = Google::Apis::AnalyticsV3::AnalyticsService.new
    analytics.authorization = Google::Auth::ServiceAccountCredentials.make_creds({
      "json_key_io": Rails.root.join('private/ga_client_secret.json'), 
      "scope": scope
    })
    analytics.authorization.fetch_access_token!
  end
end

Edit: It appears that there is some pending documentation in this pull request: https://github.com/google/google-auth-library-ruby/pull/62

It looks like the above comment answered the question(s), and since the last comment, the README has been updated with additional examples on how to use. If you are still encountering challenges here, or have trouble with the documentation, please file a new issue. 😃 Thanks!

If you already have google scopes and credentials in the hash:

@g_scopes = [Google::Apis::CalendarV3::AUTH_CALENDAR]

@config = {
  client_email: "app@app.iam.gserviceaccount.com",
  client_id: "123123123",
  private_key_id: "sadfc23rac3ca3cr",
  private_key: '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n',
  type: "service_account"
}

You can use them this way:

@credentials = Google::Auth::DefaultCredentials.make_creds(
  scope: @g_scopes,
  json_key_io: StringIO.new(@config.to_json, 'r')
)

@kevlarr, yeah, it’s odd that it is not documented. Eventually I ended up doing (after inspecting the source code):

        File.open(expand_private_path(config[:json_cred]), "r") do |json_io|
          @compute.authorization = Google::Auth::DefaultCredentials.make_creds(
              scope: config[:scopes],
              json_key_io: json_io
          )
        end

where config[:json_cred] is a file with content [1]:

{
  "private_key_id": "anotherstring",
  "private_key": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----\n",
  "client_email": "string-anotherstring@developer.gserviceaccount.com",
  "client_id": "string-anotherstring.apps.googleusercontent.com",
  "type": "service_account"
}

and scopes is ["https://www.googleapis.com/auth/compute"].

I think API can be more convenient and better documented [2].

[1] another example in spec/googleauth/credentials_spec.rb - https://github.com/google/google-auth-library-ruby/blob/master/spec/googleauth/credentials_spec.rb#L38-L44 [2] API was documented in #110

update (2008-07-24): added link to docs, private_key_id and client_id JSON elements

saved my life in 2020! thanks a lot

@zizhengwu this worked for me: (remember to store the private key in a file with new line, not with \n) http://stackoverflow.com/questions/6942600/multi-line-config-variables-in-heroku

@akostadinov your solution helped me a lot, thank you!