使用GoogleAuth无文件存储认证遇from_hash报错,求解决方案
Let's break down your problem and solve it step by step:
Why the from_hash Call is Failing
The error message says it can't find the top-level 'installed' or 'web' property, but your hash clearly has :installed — here's the catch:
The from_hash method in the googleauth gem expects string keys (like "installed"), not symbol keys (:installed). When you load credentials via from_file, the JSON parser automatically converts keys to strings, which works seamlessly. But when you manually create a hash with symbols, the method can't locate the required top-level keys it's looking for.
Quick Verification Test
You can confirm this in pry right away:
# This will throw the same error (symbol keys) creds_sym = {:installed=> {:client_id=>"[redacted]", ...}} Google::Auth::ClientId.from_hash(creds_sym) # This will work as expected (string keys) creds_str = {"installed"=> {:client_id=>"[redacted]", ...}} Google::Auth::ClientId.from_hash(creds_str)
Solution 1: Fix the Hash Key Format
If you're building the hash manually, convert all top-level keys to strings. If you're pulling the content from a JSON source (like an environment variable), parse it properly to get string keys automatically:
require 'json' # Example: Parsing JSON content from a variable creds_json = '{"installed":{"client_id":"YOUR_ID", ...}}' creds_hash = JSON.parse(creds_json) # This outputs a hash with string keys client_id = Google::Auth::ClientId.from_hash(creds_hash)
Solution 2: Store Credentials in Environment Variables (Deployment-Friendly)
To avoid storing sensitive info in files, you can use environment variables in two practical ways:
Option A: Full Credentials JSON in One Env Var
- Set the environment variable (in your
.envfile, server config, or deployment tool):GOOGLE_CREDENTIALS='{"installed":{"client_id":"YOUR_CLIENT_ID","project_id":"YOUR_PROJECT","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"YOUR_SECRET","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}' - In your Ruby code:
require 'json' creds_hash = JSON.parse(ENV['GOOGLE_CREDENTIALS']) client_id = Google::Auth::ClientId.from_hash(creds_hash)
Option B: Split Credentials into Individual Env Vars
If you prefer granular control over each credential field:
- Set separate environment variables:
GOOGLE_CLIENT_ID="YOUR_CLIENT_ID" GOOGLE_CLIENT_SECRET="YOUR_SECRET" GOOGLE_AUTH_URI="https://accounts.google.com/o/oauth2/auth" GOOGLE_TOKEN_URI="https://oauth2.googleapis.com/token" GOOGLE_CERT_URL="https://www.googleapis.com/oauth2/v1/certs" - Build the required hash manually with string keys:
creds_hash = { "installed" => { "client_id" => ENV['GOOGLE_CLIENT_ID'], "client_secret" => ENV['GOOGLE_CLIENT_SECRET'], "auth_uri" => ENV['GOOGLE_AUTH_URI'], "token_uri" => ENV['GOOGLE_TOKEN_URI'], "auth_provider_x509_cert_url" => ENV['GOOGLE_CERT_URL'], "redirect_uris" => ["urn:ietf:wg:oauth:2.0:oob", "http://localhost"] } } client_id = Google::Auth::ClientId.from_hash(creds_hash)
Quick Note on Gem Version
You're using googleauth 0.12.0 — this key-type behavior is consistent across recent versions, but if you run into further issues, double-check that your gem version aligns with the code patterns you're using.
内容的提问来源于stack exchange,提问作者LewlSauce

