How To: Simple Firebase REST API server authentication using Ruby
Published 02 December 2016 under software, firebase, real-time database, rubyonrails
Firebase is a set of tools and infrastructure which includes a real-time database. We recently needed to get a Ruby on Rails application talking to a Firebase real-time database over their REST API. Unfortunately, the documentation is somewhat scarce on how to do get authentication to work without using the deprecated auth parameter. The new way seems to be to send an access_token parameter or Authorization header as part of the request to the API. We are generating the access token using the following:
require 'jwt'
credentials = JSON.parse(File.read("credentials.json"))
private_key = OpenSSL::PKey::RSA.new credentials["private_key"]
def generate_jwt_assertion
now_seconds = Time.now.to_i
payload = {:iss => credentials["client_email"],
:aud => credentials["token_uri"],
:iat => now_seconds,
:exp => now_seconds+(60*60), # Maximum expiration time is one hour
:scope => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/firebase.database'
}
JWT.encode payload, private_key, "RS256"
end
def generate_access_token
uri = URI.parse(credentials["token_uri"])
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
req = Net::HTTP::Post.new(uri.path)
req['Cache-Control'] = "no-store"
req.set_form_data({
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
assertion: generate_jwt_assertion
})
resp = JSON.parse(https.request(req).body)
resp["access_token"]
end
credentials.json is the file we got from Project settings -> Service Accounts, GENERATE NEW PRIVATE KEY. It's also worth noting we're using the ruby jwt gem to generate the JSON web token for the assertion. This can be installed using gem install jwt.
The result from generate_access_token can then be passed either as a header or a GET parameter in our request to the API. For example, using the Authorization header in a POST request:
def post(path, data)
uri = URI.parse("https://#{credentials["project_id"]}.firebaseio.com/#{path}.json")
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
req = Net::HTTP::Post.new(uri.path)
req["Authorization"] = "Bearer #{Firebase.get_access_token}"
req.body = data.to_json
return https.request(req)
end
Comments
blog comments powered by Disqus