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:
- Obtain your GOOGLE_APPLICATION_CREDENTIALS json file by following Google's instructions here: Getting Started with Authentication
- 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.
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
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.