How can I authorize a Google Service Account without the default credentials file?

I found the answer in the source code of the google-auth-library-ruby gem.

It turns out that there is another option: take the values from the client_secrets file and put them in environment variables named GOOGLE_ACCOUNT_TYPE, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_EMAIL and GOOGLE_PRIVATE_KEY respectively.

If these keys are populated, the credentials will load from there. Not a whisper of this in the docs, though.


Since this is one of the main results that returns when searching google for "google service credentials ruby," I thought I would add my very recent experience to the list of possible answers.

Though you can do the method mentioned in the first answer, I found an alternate solution that works well with Heroku. I know it has been somewhat mentioned in another post, but the key thing that was left out was how to properly store the full GOOGLE_APPLICATION_CREDENTIALS .json file so that it can all be kept within one env on Heroku and not have special characters blow up your app when tryin to

I detail my steps below:

  1. Obtain your GOOGLE_APPLICATION_CREDENTIALS json file by following Google's instructions here: Getting Started with Authentication
  2. That will, of course, contain a json object with all the spaces, line returns, and quotations that heroku simply doesn't need. So, strip out all spaces and line breaks...AND PAY ATTENTION HERE -> EXCEPT FOR THE LINE BREAKS WITHIN THE 'BEGIN PRIVATE KEY' SEGMENT. Basically turn the json into one long string. Use whatever method you feel comfortable with.
  3. Once you have a single line json file with whitespace and line breaks removed, you will need to add it to Heroku by running the following command:

    heroku config:set GOOGLE_APPLICATION_CREDENTIALS="$(< /Users/whoever/Downloads/[CREDENTIAL_JSON_FILENAME].json)" --app your-app
    
  4. For my situation, I needed to have the service account available on initialization, so I placed this in an initializer in my rails app:

    GOOGLE_SERVICE_ACCOUNT_CREDENTIALS=Google::Auth::ServiceAccountCredentials.make_creds(
      json_key_io: StringIO.new(ENV['GOOGLE_APPLICATION_CREDENTIALS'])
    )
    

Notice the StringIO.new() method. the #make_creds wants a file. So, fake it as such by using StringIO.new.

This method works perfectly.

If you need this to work differently on your local machine, you can always store the .json somewhere in the project and reference it through a file location string. Here is my full initializer:

require 'googleauth'

#https://www.rubydoc.info/github/google/google-auth-library-ruby/Google/Auth/ServiceAccountCredentials 
if Rails.env == "test"
  GOOGLE_SERVICE_ACCOUNT_CREDENTIALS = 
Google::Auth::ServiceAccountCredentials.make_creds(
    json_key_io: File.open('lib/google/google_application_credentials.json')
  ) 
elsif Rails.env != "development"
    GOOGLE_SERVICE_ACCOUNT_CREDENTIALS = 
Google::Auth::ServiceAccountCredentials.make_creds(
    json_key_io: StringIO.new(ENV['GOOGLE_APPLICATION_CREDENTIALS'])
  ) 
end

If you are using a gem like dotenv you can store the formatted json string as an ENV or you can just reference the file location in the ENV

I hope this helps someone.